Strcpy () повреждает скопированную строку в Solaris, но не в Linux - PullRequest
3 голосов
/ 16 апреля 2010

Я пишу код C для класса. Этот класс требует, чтобы наш код компилировался и работал на школьном сервере, который является машиной sparc solaris. Я использую Linux x64.

У меня есть эта строка для анализа (ЭТО НЕ ФАКТИЧЕСКИЙ КОД, НО ВХОДИТ В МОЮ ПРОГРАММУ):

while ( cond1 ){ 

Мне нужно захватить "while" и "cond1" в отдельные строки. Я использовал strtok(), чтобы сделать это. В Linux следующие строки:

char *cond = NULL;
cond = (char *)malloc(sizeof(char));
memset(cond, 0, sizeof(char));
strcpy(cond, strtok(NULL, ": \t\(){")); //already got the "while" out of the line

будет правильно захватывать строку "cond1". Однако при выполнении этого на машине соляриса мне дается строка "cone1".

Обратите внимание, что во многих других случаях в моей программе строки копируются правильно. (Например, «пока») было записано правильно.

Кто-нибудь знает, что здесь происходит?

Ответы [ 3 ]

11 голосов
/ 16 апреля 2010

Линия:

cond = (char *)malloc(sizeof(char));

выделяет ровно один char для хранения, в которое вы затем копируете более одного - strcpy необходимо поставить, как минимум, нулевой терминатор, но, в вашем случае, также результаты вашего strtok а также.

Причина, по которой это может работать в другой системе, заключается в том, что некоторые реализации malloc будут выделять с определенным разрешением (например, кратным 16 байтам) независимо от того, какое фактическое значение вы запрашиваете, поэтому у вас может быть некоторое свободное место там в конце вашего буфера. Но то, что вы пытаетесь, все еще очень неопределенное поведение.

Тот факт, что неопределенное поведение может работать иногда, никоим образом не отменяет вашей ответственности за избежание такого поведения.

Выделите достаточно места для хранения результатов вашего strtok, и с вами все будет в порядке.

Самый безопасный способ сделать это - динамически распределять пространство так, чтобы оно было как минимум таким же большим, как строка, которую вы передаете strtok. Таким образом, не может быть возможности переполнения (кроме странных крайних случаев, когда другие потоки могут изменять данные за вашей спиной, но, если бы это было так, strtok был бы очень плохим выбором в любом случае).

Что-то вроде (если instr ваша исходная строка ввода):

cond = (char*)malloc(strlen(instr)+1);

Это гарантирует, что любой токен, извлеченный из instr, будет соответствовать cond.

Кроме того, sizeof(char) всегда равно 1 по определению, поэтому вам не нужно умножать его на *. 1030 *

2 голосов
/ 16 апреля 2010

cond выделяется один байт. strcpy копирует как минимум два байта в это распределение. То есть вы записываете больше байтов в выделение, чем имеется место.

Один из способов исправить это - использовать char *cond = malloc (1000); вместо того, что у вас есть.

1 голос
/ 16 апреля 2010

Вы выделили память только для 1 символа, но пытаетесь сохранить не менее 6 символов (вам нужно место для завершающего \ 0). Быстрый и грязный способ решить это просто сказать

char cond [128]

вместо malloc.

...