使用以下代码:
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()
范围读取会在某些系统上触发分段错误。
这是遗留代码,易于纠正。但我想知道的是可能导致这种失败与否的潜在特征。 它与堆栈上的读取违规有关吗?有些过境? 它与内存分段有关,它只是偶然的一种情况(取决于内存管理和操作系统如何完成内存分段/分页)。它可能会失败。
答案 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上的页面末尾附近,因此运行结束结果读坏记忆。