【问题标题】:Stack memory read堆栈内存读取
【发布时间】:2023-03-07 03:18:02
【问题描述】:

使用以下代码:

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 是一个以 nul 结尾的字符串,大约有 30 个字符。 使用memcpy() 读取超出fileName 范围的尝试似乎会在某些系统上触发分段错误。

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

【问题讨论】:

  • 如果参数从未更改,则应考虑将其设为 const,以便更清楚地了解其生命周期。
  • 不过,这与这种情况完全没有关系。

标签: c stack


【解决方案1】:

你已经一针见血了:

在您的 memcpy 中,您正在读取超过文件名的长度。

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        猜你喜欢
        • 2015-04-11
        • 2011-08-15
        • 2017-02-08
        • 2012-06-03
        • 2012-01-07
        • 2011-10-21
        • 2011-06-13
        • 2011-05-28
        相关资源
        最近更新 更多