堆栈内存读取

时间:2008-10-10 10:27:51

标签: c stack

使用以下代码:

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个字符。 似乎尝试使用fileName超出memcpy()范围读取会在某些系统上触发分段错误。

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

3 个答案:

答案 0 :(得分:5)

你已经敲了敲头:

在你的memcpy中,你正在阅读超过文件名的长度。

如果文件名后面的内存可读,通常也会变脏。在大多数情况下,它是,但是如果你传递一个字符串文字作为参数,并且链接器将字符串放入数据部分的最后一个千字节,你将得到一个分段错误,因为CPU试图从内存中读取未映射到流程地址空间的位置。

明显的解决方法是使用strcpy或strncpy。

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

根据给出的信息,我们不知道参数char *filename指向的位置 - 堆栈,堆,数据部分或其他...

如果它在堆栈上,可能是因为SPARC上的默认堆栈大小远大于x86上的堆栈大小,并且增长得更高。通过SPARC ABI,堆栈帧总是有空间来备份所有16个寄存器,如果函数占用任何值,则总共有6个参数的空间(即使它需要更少)。因此,每个函数调用SPARC至少消耗64或92个字节的堆栈,而x86每个函数调用只能消耗8或4个字节。

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