Это не символ новой строки, а также спецификатор формата printf. Вы обнаружили, что, возможно, ошибка в strlen()
, и я могу сказать, что вы должны использовать gcc.
Ваш код программы в порядке. Спецификатор формата printf может быть немного лучше, но это не приведет к ошибке valgrind, которую вы видите. Давайте посмотрим на эту ошибку valgrind:
==18929== Invalid read of size 4
==18929== at 0x804847E: main (in /tmp/test)
==18929== Address 0x4204050 is 40 bytes inside a block of size 41 alloc'd
==18929== at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==18929== by 0x8048415: main (in /tmp/test)
«Неверное чтение размера 4» - это первое сообщение, которое мы должны понимать. Это означает, что процессор выполнил команду, которая загрузила бы 4 последовательных байта из памяти. Следующая строка указывает, что адрес, который был прочитан, был «Адрес 0x4204050 равен 40 байтам внутри блока размера 41 alloc'd».
С помощью этой информации мы можем понять это. Во-первых, если вы замените это '\n'
на '$'
или любой другой символ, будет произведена та же ошибка. Попробуй.
Во-вторых, мы можем видеть, что ваша строка содержит 40 символов. Добавление символа завершения \0
приводит к тому, что суммарные байты используются для представления строки до 41.
Поскольку у нас есть сообщение «Адрес 0x4204050 составляет 40 байт внутри блока размером 41 alloc'd», мы теперь знаем все о том, что идет не так.
strdup()
присвоен правильный объем памяти 41 байт.
strlen()
попытался прочитать 4 байта, начиная с 40-го числа, которое будет распространяться на несуществующий 43-й байт.
- Valgrind поймал проблему
Это бойкий() ошибка. Когда-то начинался проект под названием Tiny C Compiler (TCC). По совпадению, glib был полностью изменен так, что нормальные строковые функции, такие как strlen()
, больше не существовали. Они были заменены оптимизированными версиями, которые считывают память с использованием различных методов, таких как чтение по четыре байта за раз. gcc был изменен одновременно, чтобы генерировать вызовы для соответствующих реализаций, в зависимости от выравнивания указателя ввода, скомпилированного оборудования и т. д.Проект TCC был оставлен, когда это изменение в среде GNU затруднило создание нового компилятора C, исключив возможность использования glib для стандартной библиотеки.
Если вы сообщите об ошибке, то поддерживающие glib, вероятно, не исправит ее. Причина в том, что при практическом использовании это, вероятно, никогда не приведет к фактическому сбою. Функция strlen
считывает байты 4 за раз, так как видит, что адреса выровнены по 4 байт. Всегда можно читать 4 байта из 4-байтового выровненного адреса без segfault, учитывая, что чтение 1 байта с этого адреса будет успешным. Поэтому предупреждение от valgrind не выявляет потенциального сбоя, просто несоответствие в предположениях о том, как программировать. Я считаю, что valgrind технически корректен, но я думаю, что нет никаких шансов, что разработчики glib сделают все, чтобы отменить предупреждение.
Убедитесь, что 'strdup()' прототипирован. Используйте ''% zu'' для 'strlen()'. '' \ n'' вряд ли проблема. – chux
Нет проблем с MSVC с соответствующими файлами заголовков. Где они? –
на MSVC все возможно, это не является правильной ссылкой, когда дело доходит до C – 4pie0