Вайн,
Geekoaur хорошо ответил на ваш вопрос, я просто указываю на еще одну "проблему" с вашим кодом.
Строка s1[strlen(s1)] = '\0';
- это no-op , если s1
уже правильно завершено нулем, ДО того, как выполнится.
Но если s1
НЕ уже все правильно завершено нулем, ДО того, как эта строка будет выполнена (и вам не повезло), это вызовет:
- a SIGSEGV в системе POSIX (* nix).
- a GPF в Windows.
Это потому, что strlen
в основном находит индекс существующего нулевого терминатора и возвращает его! Вот действительная неоптимизированная реализация strlen:
int strlen(char *string) {
int i = 0;
while(string[i] != '\0') {
++i;
}
return i;
}
Итак ... Если вы ДЕЙСТВИТЕЛЬНО беспокоитесь о том, что строки НЕ заканчиваются нулем, тогда вы должны сделать что-то вроде:
string[sizeof(string)]='\0';
on local автоматические строки (где компилятор "знает" размер строки);
- или
string[SIZE_OF_STRING]
для всех других строк, где SIZE_OF_STRING
является (чаще всего) константой #define
'd или переменной, которую вы поддерживаете специально для хранения текущего SIZE (не длины) динамически назначаемого строка.
И если вы ДЕЙСТВИТЕЛЬНО, ДЕЙСТВИТЕЛЬНО, ДЕЙСТВИТЕЛЬНО беспокоитесь о том, что строки не заканчиваются нулем (например, вы имеете дело с «грязными» методами библиотеки (как, например, ATMI Tuxedo)), вы ТАКЖЕ 'очистите "ваши" строки возврата перед передачей их в подозрительные методы библиотеки с помощью:
- до:
memset(string, NULL, SIZE_OF_STRING);
- invoke:
DirtyFunction(/*out*/string)
;
- после:
string[SIZE_OF_STRING]='\0'
SIG11 - это полный пакет для поиска, потому что (если вы не «зацепите» их с сигнальным процессором и не скажете иначе, они приводят к тому, что unix жестко завершает вашу программу, поэтому вы ничего не можете зарегистрировать (после факта), чтобы помочь выяснить, откуда взялся этот ад, особенно учитывая, что во многих случаях строка кода, которая выбрасывает SIG11, находится рядом с фактической причиной строки, теряющей нулевой терминатор.
Это имеет для вас смысл?
Ура, приятель. Кит.
PS: ВНИМАНИЕ: strncpy
НЕ всегда обнуляется ... вы, вероятно, имели в виду strlcpy
. Я научился этому нелегко ... когда разбился счет на 60 миллионов долларов.
РЕДАКТИРОВАТЬ:
К вашему сведению: вот «безопасная» (неоптимизированная) версия strlen, которую я назову strnlen
(полагаю, это должно быть в stdlib . Sigh.).
// retuns the length of the string (capped at size-1)
int strnlen(char *string, int size) {
int i = 0;
while( i<size && string[i]!='\0' ) {
++i;
}
return i;
}