Уменьшите длину строки в c, где ошибка? - PullRequest
0 голосов
/ 20 февраля 2012

У меня есть два разных имени файла, которые определены в заголовочном файле:

1: "physio_sensor_readout.csv" 2: "statethresh_configuration.csv"

они инициализируются

char* filename;

и позже

filename = FILENAMEINAMACRO; which is the corresponding filename above

Позже имя файла передается другой функции, которая изменяет окончание:

filename[strnlen(filename, FILENAME_LENGTH) - 4] = '\0';

Это должно удалить окончание .csv и i strncat aновый потом.FILENAME_LENGTH - 60, поэтому достаточно места.

Это работает, если я передаю «statetresh _....» (даже strncat впоследствии), но не с «physio_se .....».Это выдает ошибку сегмента

strnlen(filename,FILENAME_LENGTH - 4)

возвращает 21 в случае 1 и 25 в случае 2. Это правильная позиция точки, где я хочу поставить завершающий ноль.

Это проблема с char *, и я должен инициализировать имя файла с именем char [60]?

С уважением и благодарностью

edit:

yourпредложения решили проблему.спасибо!

Ответы [ 3 ]

2 голосов
/ 20 февраля 2012

Не безопасно изменять содержимое символьного литерала. Примерно так:

char *filename = "yes";
filename[2] = 'p'; // change to "yep"

- неопределенное поведение, которое может привести к катастрофическим результатам, поскольку filename может указывать на память, которую нельзя изменить. Вместо этого попробуйте что-то вроде этого:

char filename[] = "yes";
filename[2] = 'p'; // change to "yep"

, который выделит новый массив filename и инициализирует его содержимое с "yes".

2 голосов
/ 20 февраля 2012

I думаю вы объявляете FILENAMEINAMACRO как строковый литерал [Без кода я не могу быть в этом уверен].

строковые литералы могут быть сохранены при чтениитолько память - так что вы не сможете их изменить.

Любая попытка изменить строковые литералы приводит к неопределенному поведению.

Возможно, вы захотите сделать копию FILENAMEINAMACROи работаем над этим, используя strcpy()

0 голосов
/ 20 февраля 2012

Вы, кажется, указываете свой символ * указатель filename на символьную константу. Я полагаю, вы определили #define FILENAMEINAMACRO "physio_sensor_readout.csv". Это делает ваше назначение filename = "physio_sensor_readout.csv";. Затем вы используете указатель имени файла для изменения строковой константы. Вот более подходящая последовательность:

char filename[256];   // choose a size that is suitably large
...
strcpy(filename, FILENAMEINAMACRO);  // also look at strncpy for safer copying
...
... manipulate the content of filename as you wish ...

Поскольку вы сделали копию строкового литерала, его изменение безопасно (если вы остаетесь в пределах заявленного размера filename, что включает в себя сохранение любого завершающего нуля также в пределах границ.

Вы должны быть осторожны, используя форму char filename[] = "...". Он выделяет достаточно места для строкового литерала, который вы ему даете, но если позже вы копируете какой-то другой строковый литерал в это пространство, вы должны быть уверены, что второй литерал не длиннее первого. Более безопасная практика - измерять пространство так, чтобы оно было достаточно большим, чтобы вы были уверены, что ваш код никогда не будет пытаться использовать больше, чем то, что вы измерили. Если вы принимаете ввод извне программы (или из кода другого человека), вы должны проверить длину того, что вы принимаете, прежде чем пытаться скопировать его в пространство, которое вы измерили. Любое использование пространства сверх размерного размера может вызвать проблемы, которые трудно диагностировать. В приведенном выше примере вы должны приложить все усилия, чтобы гарантировать, что вы никогда не будете использовать больше места (включая завершающий nul символ), чем 256 символов (поскольку имя файла имеет размер 200).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...