2010-11-20 7 views
14

Mój program wygląda następująco;Dlaczego użycie niewłaściwego specyfikatora formatu w C powoduje awarię mojego programu w systemie Windows 7?

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

int main() 
{ 
     char string[] = "Gentlemen start your engines!"; 
     printf("That string is %s characters long.\r\n", strlen(string)); 
     return 0; 
} 

Kompiluję pod gcc i chociaż nie daje mi żadnych błędów, program ulega awarii za każdym razem, gdy go uruchomię. Kod wydaje się być dobry z przykładów, które widziałem. Byłoby świetnie wiedzieć, czy robię coś złego.

Dzięki.

+0

Dziękuję wszystkim. Powinienem był to zauważyć, dopiero zaczynałem od C i bawiłem się z programami tekstowymi tylko za pomocą łańcuchów tylko do tej pory, więc% s właśnie automatycznie przyszło na myśl. – austinprete

+4

+1, ponieważ nauczyłem się, że powinienem używać% zu cały czas zamiast tylko% u lub nawet% d –

+1

Jeśli używasz GCC, podkręć swoje błędy za pomocą '-Wall' lub może' -Wextra' lub może '-Werror'. GCC może sprawdzić ciąg formatu i ostrzegać o błędnych argumentach dla funkcji 'printf'-,' scanf'-, 'strftime'- i' strfmon'-like. –

Odpowiedz

16

Korzystanie Nieprawidłowy format specyfikatora w printf() wywołuje zachowanie niezdefiniowane. Poprawny format specifier powinny być %zu (nie %d), ponieważ typ powrót strlen() jest size_t

Uwaga: Długość modyfikator z w %zu oznacza liczbę całkowitą długość same jak size_t

+0

Kiedy gcc w systemie Windows przestał używać Microsoft CRT? Mam błędy po raz ostatni użyłem% zu na MinGW, czy jest tam inna wersja gcc, która używa glib? –

+0

@Pete: Nie powinieneś otrzymywać takich błędów. Upewnij się, że korzystasz z najnowszej wersji MinGW z obsługą C99. –

+0

Słodkie! Każda ETA dla MingW implementująca emulowane ustawienia regionalne UTF-8 na wierzchu funkcji '_wfopen' itd.? –

2
printf("That string is %d characters long.\r\n", strlen(string)); 

zamiast:

printf("That string is %s characters long.\r\n", strlen(string)); 
+0

jeszcze jedno, zmień nazwę zmiennej "string" na inną. "ciąg" jest słowem zastrzeżonym. –

+0

OK, dziękuję.Użyłem "ciągu", aby złożyć szybki program, który ma długość łańcucha, ponieważ piszę program, który wykrywa palindromy i chciałbym się zorientować, jak to zrobię. Będę jednak pamiętać, aby nie używać go w przyszłości. – austinprete

+0

Syntaktycznie, 'ciąg' nie jest słowem kluczowym. Jest to jednak, jak wszystkie nazwy zaczynające się od 'str',' mem' lub 'wcs'," zarezerwowane do przyszłego użytku "jako funkcja łańcuchowa w nagłówku' '. (źródło: ISO C99, 7.26.11) –

7

masz niewłaściwy format specyfikatora. %s jest używany do ciągów znaków, ale przechodzisz pod numer size_t (strlen(string)). Używanie niepoprawnego specyfikatora formatu w printf() wywołuje niezdefiniowane zachowanie. Zamiast tego należy użyć %zu, ponieważ typem zwrotu strlen() jest size_t.

Więc zmienić

printf("That string is %s characters long.\r\n", strlen(string)); 

do:

printf("That string is %zu characters long.\r\n", strlen(string)); 

Ponieważ używasz gcc spojrzeć here uzyskać więcej informacji, co może być przekazany do printf

+1

Użycie 'gcc' do kompilacji niekoniecznie oznacza, że ​​używasz glibc do wykonywania kodu. –

2

Masz problem tutaj printf("That string is %s characters long.\r\n", strlen(string));

umieścić

printf("That string is %d characters long.\r\n", strlen(string)); % d, ponieważ chcesz DrukujZestaw długość słowo (strlen Number Zwraca)

1

awarii programu, ponieważ formatowanie rutynowych próbuje uzyskać dostęp do łańcuch na adres 0x0000001D, która jest wynikiem strlen() gdzie ma nic jak ciąg i najprawdopodobniej nie ma dostępnej pamięci.

Powiązane problemy