今天在定位问题时,发现有一个字符串关键字在搜索时死活不命中,但实际那个关键字在数据中是存在的,跟踪发现是一个不起眼的细节导致的。

用一段简短的代码来说明一下问题出在哪里:

#include <stdio.h>

#define M_STRING_1 "test"
#define M_STRING_2 (char *)"test"

int main(int argc, char *argv[])
{
    char *pcStr = M_STRING_1;

    printf("Size of string macro 1      : %u bytes \r\n", sizeof(M_STRING_1));
    printf("Size of string pointer 1    : %u bytes \r\n", sizeof(pcStr));
    printf("Size of string macro 2      : %u bytes \r\n", sizeof(M_STRING_2));

    return 0;
}

程序运行结果:

Size of string macro 1      : 5 bytes 
Size of string pointer 1    : 8 bytes 
Size of string macro 2      : 8 bytes

第一行:宏定义字符串长度为4字节,sizeof(M_STRING_1)加上0x00结束符,大小是5字节没问题。 第二行sizeof(pcStr)是在计算指针的长度,计算出的值和CPU寄存器的宽度有关,我的机器是64位,所以得到的大小是8字节,这个也是在预料之中。 第三行:问题就发生在这里,本来以为会和第一行计算结果一样是5字节,实际结果却是预料之外的8字节(指针长度)!

分析发现,M_STRING_2宏定义中的字符串多了一个(char *)的强制转换,正是这个转换导致sizeof的入参从字符串常量变成了指针,从而计算出的大小为指针的长度而非字符串的大小。

开头提到的关键字不匹配问题,也正是由于关键字长度超出实际值,导致访问越界,而越界部分的值是不可预知的,最终造成了无法命中的问题。


Comments