2009-07-24 3 views
4

Я использую ниже кодstrncpy и с помощью SizeOf для копирования Максимального количества символов

char call[64] = {'\0'} /* clean buffer */ 
strncpy(call, info.called, sizeof(call)); 

Я всегда использую SizeOf для назначения для защиты переполнения, упаковывает источник больше, чем назначения. Таким образом, я могу предотвратить переполнение буфера, поскольку он будет копировать столько, сколько может обрабатывать адресат.

Но теперь я задаюсь вопросом, не приведет ли он к прекращению назначения.

Пару случаев.

1) Если источник больше. я мог бы сделать это:

call[strlen(call) - 1] = '\0'; /* insert a null at the last element.*/ 

2) Если источник меньше назначения. вызов - 64 байта, и я копирую 50 байт, так как это размер источника. Будет ли он автоматически помещать нуль в элемент 51?

Большое спасибо за любую информацию,

ответ

4

Если длина источника составляет менее максимальное число, переданное третьим параметром strncpy, будет нулевым - прекратить назначение, в противном случае - нет.

Если источник равен или больше по длине, чем пункт назначения - это ваша проблема с этим. Выполнение, как вы предлагаете - вызов strlen() - не будет работать, поскольку буфер не будет завершен с нулевой отметкой, и вы столкнетесь с неопределенным поведением.

Можно выделить больший буфер:

char buffer[bufferSize + 1]; 
strncpy(buffer, source, bufferSize); 
*(buffer + bufferSize) = 0; 
4

Ваша идея:

call[strlen(call) - 1] = '\0'; 

не будет работать, как вы бы называть strlen() на незавершенных строки

12

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

strncpy(call, info.called, sizeof(call) - 1); 
call[sizeof(call) - 1] = '\0'; 

BSD и даже strlcpy(), среди других, как правило, считается выше:

http://www.openbsd.org/cgi-bin/man.cgi?query=strlcpy

+0

Один простой способ гарантировать, что конечный пункт nul завершен здесь, чтобы выполнить вызов [sizeof call -1] = 0; – nos

+0

Я не думал, что strncpy завершит строку. Не завершая строку. Может ли это привести к реальной проблеме? Кроме того, выполняя этот вызов [strlen (info.called - 1] = '\ 0 "; что это правильный способ прекратить работу, если источник больше или меньше адресата? Спасибо. – ant2009

+0

Да, строка с неисчерпаемыми символами приведет к' strlen() ',' strcat() 'и т. д., чтобы быть неправильным, поврежденной памятью и/или сбоем. Установка последнего байта буфера на ноль ничего не наносит, когда строка короче места назначения, поэтому нет причин для того, чтобы сделать его условным. –

1

Но я Теперь я задаюсь вопросом, не приведет ли это к прекращению назначения.

Нет, strncpy не обещает, что целевая строка будет завершена нулем.

char tar[2]={0,0}; 
char bar="AB"; 
strncpy(tar,bar,2); 
// result tar[0]=='A'; tar[1]=='B' 

Это для того, чтобы сделать это правильно, вы должны использовать:

strncpy(traget,string,sizeof(target)-1); 
target[sizeof(target)-1]=0 
+0

Мне просто интересно. Есть ли какая-либо реальная разница в использовании strlen или sizeof? – ant2009

+0

sizeof является постоянным, он возвращает sizeof objet, когда strlen фактически вычисляет в runtime длину строки. Например, для char tar [2] = {0,0}; sizeof (tar) == 2, но strlen (tar) == 0; – Artyom

1

1) От cplusplus.com: «Нет нуль-символ не неявно добавляется к концу назначения, поэтому назначения будет только нуль- если длина строки C в источнике меньше, чем num. " Таким образом, вы, если вам нужна ваша строка будет завершающим нулем, вам нужно сделать, это:

call[sizeof(call) - 1] = '\0'; 

Хороший способ сделать это было бы написать функцию-обертку для strncpy, что всегда делает, что строка завершается.

2) Если источник короче места назначения, назначение будет заканчиваться нулем.

0

Просто используйте strlcpy() вместо strncpy(). Вам нужно будет проверить, доступно ли это на всех платформах. Ранние версии Linux, возможно, не имеют его.

+0

Это не стандартная функция. Он может быть недоступен. –

Смежные вопросы