尝试从常量 char * 类型的指针复制数据时出现“超出内存访问”错误。为啥?

Posted

技术标签:

【中文标题】尝试从常量 char * 类型的指针复制数据时出现“超出内存访问”错误。为啥?【英文标题】:Getting "accessing beyond memory" error when it is tried to copy data from a pointer of type constant char *. Why?尝试从常量 char * 类型的指针复制数据时出现“超出内存访问”错误。为什么? 【发布时间】:2014-03-31 10:41:20 【问题描述】:

以下语句引发超出内存错误的访问。我仍然不确定它为什么会那样做。谁能帮我在这里做错了什么?谢谢

    memcpy(mhp_ptr->dpair[0].dpairid, id0, 8);

这里 id0 的类型是 const char *

其中,mhp_ptr 是 mhp_t * 类型,其定义如下:-

typedef struct mhp_s 
 
    uint8_t  editor[16];
    uint64_t refcode;
    uint64_t error_id;
    union
    
        uint8_t dpairtbl[16][6];
        dpairtbl_t dpair[6];
    ;
  mhp_t;

而dpairtbl_t定义如下:-

typedef struct dpairtbl_s
 
    char  dpairid[8];
    uint64_t dpairdata;
 dpairtbl_t;

错误:- 访问超出分配的内存 “memcpy”可以从缓冲区“id0”中读取 8 个字节

我的项目的编译器设置将警告视为错误。正常编译工作正常,但它发出一个警告,根据我的编译器中的设置被视为错误。 只是想知道为什么它对 strcpy 工作正常,但在 memcpy 的情况下发出警告。在字符串的情况下,对 memcpy 的使用是否有任何 C++ 限制

【问题讨论】:

嗯,id0 指向的内存是多少? 您将 8 个字符的大小 + 一个 int64 写入包含 8 个字符的内存中。 id0 是 const char* 类型。如果我使用 strcpy 它可以正常工作,我不会收到任何错误,但如果我使用 memcpy 它会引发错误 【参考方案1】:

memcpy 视为内存中字节的复制:

memcpy(mhp_ptr->dpair[0].dpairid, id0, 8);

如果id0的长度小于8,memcpy也会复制不属于你的内存,如果是8个或更多字符,dpairid不会为null-正确终止。

如果您无法保证 id0 的大小正好是 8 个字节,则应将其视为字符串,以便根据终止字符确定长度:

strncpy (mhp_ptr->dpair[0].dpairid, id0, 7);
mhp_ptr->dpair[0].dpairid[7] = '\0';

【讨论】:

即使我使用 8 而不是 sizeof(dpairtbl_t) 也会引发错误,抱歉编辑了问题以避免混淆 @user3480704:告诉我们id0是如何定义和初始化的。 @user3480704 然后我们回到 id0 中有什么的问题 id0 被定义为 const char * id0 作为功能参数之一。它基本上包含提供错误信息的字符串。【参考方案2】:

一个潜在的问题是您正在复制到 dpairid(大小为 8),大小为 dpairtbl_t(可能为 16)

要么你的尺寸有误(使用 sizeof(dpairid)),要么

typedef struct dpairtbl_u
 
     char  dpairid[8];
     uint64_t dpairdata;
 dpairtbl_t;

应该是联合

typedef union dpairtbl_u
 
     char  dpairid[8];
     uint64_t dpairdata;
 dpairtbl_t;

【讨论】:

它只是 struct 类型,如果我使用 strcpy,它可以正常工作,但在 memcpy 的情况下会引发错误。抱歉造成混淆,编辑问题以进一步澄清 @user3480704 with strcpy 如果 id0 的长度小于 8,它将起作用,因为 strcpy 在找到字符串末尾的 '\0' 时停止。 是的,这正是为什么对于任何未来与字符串相关的操作,我想知道 memcpy 是否是正确的前进方式 如果可以,请使用 std::string ...要复制的字符数(以免超出目标缓冲区)。【参考方案3】:

除了其他答案之外,我没有收到任何错误并且它有效。这是我的代码:

const char* id0 = "*** question";
mhp_t* mhp_ptr = new mhp_t;

memcpy(mhp_ptr->dpair[0].dpairid, id0, sizeof(dpairtbl_t));

cout << mhp_ptr->dpair[0].dpairid << endl;

delete mhp_ptr;

输出是:

stackove

当我查看sizeof(dpairtbl_t) 值时,它是8。也许您忘记了指针mhp_ptr 的分配/初始化。以及如何初始化id0

【讨论】:

id0 作为字符串传递。正常编译工作正常,但它发出一个警告,根据我的编译器中的设置被视为错误。只是想知道为什么它对 strcpy 工作正常但在 memcpy 的情况下发出警告。有C++限制吗?

以上是关于尝试从常量 char * 类型的指针复制数据时出现“超出内存访问”错误。为啥?的主要内容,如果未能解决你的问题,请参考以下文章

尝试使用指向 char* 的指针时出现总线错误 10 或分段错误 11,具体取决于封装

尝试使用 pyspark 从 S3 获取数据时出现空指针异常

尝试从 Apache Beam 中的选项获取值时出现空指针异常

从firebase检索时出现空指针异常[重复]

尝试从方法返回指向对象的指针时出现分段错误

从应用程序创建 SQLite 数据库时出现空指针异常 [重复]