Ошибка сегментации - указатель символа

В приведенном ниже коде строка:

*end = *front;

дает ошибку сегментации. Я задал аналогичный вопрос здесь, но я не уверен, что это потому, что у меня два экземпляра ном. Пожалуйста, объясните, почему это seg-fault. Спасибо.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* getPalin(char* num);

int main()
{
    char* num = (char*)malloc(100);

    num = "123456";

    printf("%s\n", getPalin(num) );

    return 0;
}

char* getPalin(char* num)
{
    int length = strlen(num);

    if ( length % 2 == 0 )
    {
        char* front = num;
        char* end = num + strlen(num) - 1;  //pointer to end

        while( front != num + (length/2) )  //pointers not middle yet
        {
            *end = *front;

            printf("%c", *end);

            front++;
            end--;
        }
    }

    return num;
}

person Mike Anderson    schedule 03.06.2009    source источник


Ответы (4)


Эти две строки:

char* num = (char*)malloc(100);
num = "123456";

иметь следующий эффект.

Первый выделяет 100 байтов и устанавливает num для указания на эти байты.

Второй изменяет num, чтобы указать на строку «123456», которая почти наверняка находится в постоянной памяти.

Любая попытка изменить содержимое постоянной памяти приведет к нарушению сегментации. Вам нужно скопировать строку в malloc'd num, прежде чем пытаться ее изменить, с помощью:

strcpy (num, "123456");

Это строка, которую вы должны иметь там, где у вас сейчас есть:

num = "123456";
person paxdiablo    schedule 03.06.2009

Использовать

strncpy(num, "123456", 100);

вместо

num = "123456";
person Konstantin    schedule 03.06.2009
comment
извините, не sizeof(num), а размер выделенной памяти, то есть 100. Т.е. strncpy(число, 123456, 100); - person Konstantin; 03.06.2009
comment
ОП попросил объяснений, но вы дали только решение. И никогда не забывайте вручную добавлять нуль-терминатор после strncpy, потому что не гарантируется, что strncpy добавит его. Я знаю, что это не имеет значения в этом примере, потому что 123456 короче 100 байт, но если вы решили использовать strncpy, а не strcpy, используйте его правильно - вы избежали одной потенциальной проблемы (переполнение буфера), но добавили другую (незавершенную строку). - person qrdl; 03.06.2009
comment
@qrdl - Пока размер места назначения, указанный в strncpy, больше длины строки, strncpy автоматически дополняется нулевыми символами. Только если целевой размер указан как меньший, чем длина копируемой строки, нулевой терминатор может быть пропущен. Еще один момент — помнить, что strncpy НЕ будет проверять наличие достаточного места в целевой памяти. Поэтому я полагаю, что strncpy(num,123456, sizeof(num)) будет более правильным. - person ChrisBD; 03.06.2009
comment
num — это char*, поэтому sizeof(num) будет равен 4 (или 8, если у вас аппаратное обеспечение лучше, чем у меня). - person paxdiablo; 03.06.2009
comment
@ChrisBD - прочитайте мой комментарий внимательнее. Я же написал, что знаю, что это не важно в данном случае. И просто к вашему сведению - sizeof(num) в этом случае является sizeof(char ), потому что num объявлен как char в списке параметров. - person qrdl; 03.06.2009
comment
Да, вы совершенно правы насчет sizeof. Было бы нормально, если бы число было определено как char num[100]; В этом случае нет способа программно определить объем памяти, выделенный malloc. - person ChrisBD; 03.06.2009
comment
Лучше никогда не использовать strncpy, так как он предназначен для заполнения полей фиксированного размера, это не обычная функция обработки строк. - person vonbrand; 20.01.2013
comment
Я думаю, что с strncpy все в порядке, если понимать, что strncpy работает с полями фиксированного размера, а не со строками. Стандарт C, похоже, определяет strncpy как строковую функцию, поэтому я бы назвал ее общей функцией обработки строк; Общая обработка строк не обязательно означает вывод строки. Также можно заставить поле фиксированного размера быть строкой. Рассмотрим char dest[n]; dest[n-1] = '\0'; strncpy(dest, source, n - 1);. - person autistic; 21.01.2013

Согласно ответу Константина.

Вы уже выделили память для num с помощью оператора malloc.

Если бы вы этого не сделали, вы могли бы уйти с:

char* num = "123456";

Который будет определять и выделять память на лету, но, скорее всего, она будет выделяться как константа и, следовательно, только для чтения.

Использование strncpy вместо strcpy для копирования «123456» гарантирует, что любое дополнительное пространство за пределами конца нулевого терминатора строки также будет инициализировано значением null, если вы укажете n равным 100 (для вашего примера). В противном случае без инициализации памяти, выделенной malloc, значением null (memset(num, 0, 100)), возможно, вы могли бы выйти за пределы конца строки.

О, чуть не забыл. Желательно использовать strcpy_s или strncpy_s, так как они более безопасны, хотя для вашего кода это не имеет значения.

person ChrisBD    schedule 03.06.2009
comment
На самом деле я считаю эти две функции _s() костылем для людей, которые не знают, как защищаться от кода [т. е. сначала проверять предварительные условия — я даже никогда не находил необходимости использовать strncpy(), и все же мой код такой же, как безопасный, как и любой другой, использующий варианты _s()]. Кроме того, они еще не являются частью стандарта. - person paxdiablo; 03.06.2009
comment
Отсюда и причина, по которой я сказал целесообразно. Меня не перестает удивлять, как много коммерческого программного обеспечения оставляет себя открытым для атак с переполнением буфера. - person ChrisBD; 03.06.2009

Причина ошибки:

  char* num = (char*)malloc(100);

В этой строке вы объявили num как указатель на массив или указатель на его первый элемент, а не как строку.

 num = "123456";

В этой строке вы использовали num, поскольку объявили ее как строку. Это нарушение сегментации и, следовательно, ошибка seg. Предпочтительный (правильный) синтаксис для вашего кода:

   char num[100];
   strcpy(num,"123456"); //Even if you use num="123456"; here it would still be wrong

OR

  char* num = (char*)malloc(100);
  strcpy(num,"123456");

OR

  char num[100]={'1','2','3','4','5','6'};

Любой из них сделает вашу работу.

person Optimus Prime    schedule 13.10.2012