2015-07-21 3 views
-1

Когда я %u в sprintf() приложения получает разбился, он прекрасно работает с %dФормат спецификатор% U используется с Sprintf создает аварии

Смотрите код:

#include <stdio.h> 
#include <string.h> 
main() 
{ 
    unsigned char dAddr[4]; 
    unsigned char sMask[4]; 
    unsigned char nHop[4]; 
    memset(dAddr,0,sizeof(dAddr)); 
    memset(sMask,0,sizeof(sMask)); 
    memset(nHop,0,sizeof(nHop)); 
    unsigned int u4IpDAddr = 0x01020304; 
    unsigned int u4IpSNetMask = 0xffff01ff; 
    unsigned int u4NHopGt = 0x01020304; 
    char *dip = (char *)&u4IpDAddr; 
    char *smk = (char *)&u4IpSNetMask; 
    char *nhp = (char *)&u4NHopGt; 
    sprintf(dAddr, "%u.%u.%u.%u", dip[3], dip[2], dip[1], dip[0]); //if I used %d.%d.%d.%d its working fine 
    sprintf(sMask, "%u.%u.%u.%u", smk[3], smk[2], smk[1], smk[0]); //if I used %d.%d.%d.%d its working fine 
    sprintf(nHop, "%u.%u.%u.%u", nhp[3], nhp[2], nhp[1], nhp[0]); //if I used %d.%d.%d.%d its working fine 
    printf("SAM: func %s line %d IpDAddr %s Mask %s NHop %s\n",__func__,__LINE__,dAddr,sMask,nHop); 
} 

, когда я объявил указатель с следующий манера его прекрасно работать для %u.%u.%u.%u формата

unsigned char *dip = (unsigned char *)&u4IpDAddr; 
unsigned char *smk = (unsigned char *)&u4IpSNetMask; 
unsigned char *nhp = (unsigned char *)&u4NHopGt; 

Может ли один объяснить, что я когда я использовал char указателей?

+4

Это сумасшедший код. Что вы пытаетесь сделать в мире? – ooga

+2

Сурав уже дал единственный реальный ответ.Вы оборачиваете границы своих массивов (в обоих направлениях), и результаты не определены. Однако, в зависимости от ваших данных и подписанности «char» по умолчанию в вашей среде, может быть, что вы перехватываете свои массивы * больше *, когда используете простые указатели «char», в результате переинтерпретации отрицательного числа со знаком ('char' продвигается до' int') как неподписанный. Это может объяснить, почему наблюдаемые (неопределенные) результаты различаются. –

+0

Использование '% u' с' smk' вызовет неопределенное поведение. '% u' предназначен только для печати беззнаковых int (или int с неотрицательными значениями), но некоторые из значений' smk' являются отрицательными символами. –

ответ

9

В вашем случае

unsigned char dAddr[4]; 
unsigned char sMask[4]; 
unsigned char nHop[4]; 

не достаточно, чтобы держать лексикографическом выход.

Когда вы используете эти массивы в качестве строки назначения в sprintf(), по сути, вы обходите выделенную память, создавая undefined behaviour.

Вам необходимо выделить больше памяти для использования этих массивов в качестве адресата sprintf().

1

Если char подписан на вашей платформе, то char значение, которое вы «вырубить» вашего u4IpSNetMask более чем вероятно, будет отрицательным, так как у вас есть байты, которые начинаются с 0xF... в u4IpSNetMask. Когда вы отправляете такие значения char в sprintf, они преобразуются в отрицательные значения int, а затем переинтерпретируются как unsigned значениями вашего %u. Поведение на самом деле не определено - это не соответствует sprintf отрицательным int значениям с %u. Однако на практике вы обычно получаете огромные положительные значения, которые требуют представления многих символов. Эти представления легко переполняют ваши целевые буферы, уничтожают стек программ и приводят к сбою вашей программы.

Вы можете увидеть, что ваши sprintf вызовы порождают на типичной платформе: http://coliru.stacked-crooked.com/a/6aec03cfdf28f8b2

Средний sprintf производит 4294967295.4294967295.1.4294967295. И вы ожидали, что этот монстр поместится в буфер sMask длиной всего 4 символа?

Кроме того, тот же самый вид переполнения происходит с %d как хорошо, но строковое представление производится %d короче (-1 вместо 4294967295) ущерб меньше, что, вероятно, поэтому программа своего рода лимпит к конец без сбоев. Но это не меняет того факта, что строка 1.2.3.4 требует буфера символов длиной не менее 8 символов. Вы предоставили только 4.

Другими словами, ваша программа разбита на %d так как она разбита на %u. Если он не сбой с %d, это просто случайно.

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

  • Нет связанных вопросов^_^