1

使用以下代码:

typedef struct
{
    char    fileName[ 1024];
    time_t  deleteTime; 
} file_item_t;

....
....

setEntry(char *fileName)
{
    file_item_t     file;

    memset( &file, 0x00, sizeof( file_item_t ));

    memcpy( file.fileName, 
         fileName, 
         sizeof( file.fileName ) - 1 );
...
...

调用该函数时,它在 SPARC 机器上运行正常,但在运行 Solaris 10 的 i386 上出现 段错误fileName。假设是一个以空字符结尾的字符串,大约 30 个字符。似乎尝试读取超出使用范围fileNamememcpy()触发某些系统上的分段错误。

它是遗留代码,易于纠正。但我想知道的是可能导致失败与否的潜在特征。它与堆栈上的读取冲突有关吗?一些跨界?它与内存分段有关,它是否只是偶然的情况(取决于内存管理和操作系统如何完成内存分段/分页。)它可能会失败。

4

3 回答 3

5

You already hit the nail on the head:

In your memcpy you're reading past the length of filename.

Also dirty that will often work if the memory behind the filename is readable. In most cases it is, but if you for example pass a string-literal as an argument, and the linker puts the string into the last kilobyte of the data-section you will get a segmentation fault because the CPU tries to read from a memory location that is not mapped into the address space of your process.

The obvious fix is to use strcpy or strncpy.

于 2008-10-10T10:33:57.297 回答
1

您确定 所指向的字符串fileName的长度真的是 1024 字节吗?不知何故,我觉得你应该 strcpy 而不是 memcpy。

如果 fileName 更短,memcpy 会复制真实字符串数据后面的字节,并且可能会导致读取该内存的访问冲突。

于 2008-10-10T10:31:01.263 回答
1

有了给定的信息,我们不知道参数char *filename指向的位置——堆栈、堆、数据部分或其他......

如果它在堆栈上,可能是因为 SPARC 上的默认堆栈大小比 x86 上的大得多,而且增长得更高。根据 SPARC ABI,堆栈帧始终有空间来备份所有 16 个寄存器,如果函数需要任何参数(即使它需要更少),还可以为六个参数加上空间。因此,SPARC 每次函数调用至少消耗 64 或 92 字节的堆栈,而 x86 每次函数调用只需 8 或 4 字节即可。

如果它在堆上或数据部分中,那么可能只是运行时(堆)或编译器(数据)碰巧将字符串放在 x86 上页面的末尾附近,因此运行结束会导致读取错误记忆。

于 2008-10-10T14:54:27.803 回答