C: strncpy больше символов, чем выделено, затем печать ... неожиданный вывод? - PullRequest
0 голосов
/ 08 марта 2012

В некоторых примерах кода, предоставленных профессором:

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

int main()
{
  char alpha[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  printf( "%s\n", alpha );
  printf( "%c\n", alpha[8] );
  alpha[8] = 'Z';   /* segmentation fault if alpha is declared statically! */

  printf( "%d\n", sizeof( alpha ) );
  printf( "%d\n", strlen( alpha ) );

  char x[10];
  strncpy( x, alpha, 26 );
   /* strncpy() will NOT copy or append a '\0' */
  printf( "%s\n", x );

  return EXIT_SUCCESS;
}

При первой компиляции и запуске программы происходит сбой из-за того, что, как я вижу, в течение нескольких минут работы с Google, механизм защиты gcc от буферапереполнение (вызвано printf( "%s\n", x );, в котором x был заполнен 26 байтами от альфы).Я верю, что понимаю это.

Однако при отключении механизма защиты с помощью gcc -fno-stack-protector вывод, который я вижу:

ABCDEFGHIJKLMNOPQRSTUVWXYZ
I
27
26
ABCDEFGHZJKLMNOPQRSTUVWXYZKLMNOPQRSTUVWXYZ

Я подумал, что, поскольку strncpy не завершает нуль, завершает строку, этокогда печатается X, он может фактически напечатать полное значение alpha - но на самом деле он печатает все alpha, а затем еще немного alpha!

Может ли кто-нибудь дать здесь некоторое представление

Ответы [ 4 ]

2 голосов
/ 08 марта 2012
 char x[10];   strncpy( x, alpha, 26 );    
/* strncpy() will NOT copy or append a '\0' */   
printf( "%s\n", x ); 

В strncpy вы передаете 26 как значение n, поэтому он копирует 26 символов, но при печати с использованием printf printf попытается найти '\ 0' в качестве завершающего символа длястрока.В этом случае каким-то образом «\ 0» присутствует после «KLMNOPQRSTUVWXYZ».

Таким образом, в действительности, когда вы делаете массив вне границ, вы можете получить любой результат, падение, слишком длинную строку и т. Д.

2 голосов
/ 08 марта 2012

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

Неопределенное поведение означает, что любое поведение возможно, оно всегда не должно приводить к ошибке сегментации. Это просто означает, что программа недопустима и может показать любое поведение.

Да, ваша программа может даже иногда работать так, как хотелось бы, но она по-прежнему сформирована как стандартная программа.

1 голос
/ 08 марта 2012

С этим кодом:

   char x[10];
   strncpy( x, alpha, 26 );

Вы копируете 26 байтов данных в 10-байтовый массив, что означает, что вы перезаписываете 16 байтов любой памяти, которая оказалась смежной с "x". В этом случае похоже, что то, что было смежно с «x», было «альфа», поэтому вы засорили часть вашего исходного массива

Когда вы «печатаете» x, он продолжает печатать до тех пор, пока не достигнет нулевого байта, поэтому он распечатывает все 26 скопированных вами байтов, плюс все остальное, что находится в памяти (оставшееся содержимое «alpha»), до следующего нулевого байта .

1 голос
/ 08 марта 2012

Вопрос по разметке памяти.В этой программе «альфа» находится сразу за «х».поэтому, когда вы звоните

strncpy( x, alpha, 26 );

, данные альфа изменяются.

...