【问题标题】:Memcpy causing a seg fault in strcpy? Valgrind output included [closed]Memcpy 导致 strcpy 中的段错误?包括 Valgrind 输出[关闭]
【发布时间】:2014-10-18 19:34:59
【问题描述】:

我尝试复制我在项目中遇到的这个错误,但所有努力都失败了,我的复制完美地编译和测试。

基本上,我不断收到一个段错误,该错误可追溯到我的一个文件中对strcpy 的调用。我已经设法在一定程度上隔离了它,并且倾向于认为问题是由于之前对 memcpy 的调用造成的,因为没有该行,代码可以正常工作。

void play(char * p1, char * p2, 
    struct result * final_res)
{
    enum icons my_board[WIDTH][HEIGHT];
    initialize(my_board);  /* potentially causing the seg fault */

    strcpy(final_res -> won, "Hello"); /* the seg fault */
    strcpy(final_res -> lost, "Goodbye"); 

    /* rest of my code, commented out */
}

result 中的结构体:

struct result
{
    char won[21];
    char lost[21];
};

有问题的函数,它复制全局枚举的状态,master

void intialize(enum icons board[][WIDTH])
{
    int i, j;

    for(i=0; i < WIDTH; i++) {
        for(j=0; j < WIDTH; j++) {
            memcpy(&board[i][j], &master[i][j], WIDTH-1);
        }
    }

}

master 全局变量:

static const enum icons master[WIDTH][HEIGHT] = 
{
    {CIRCLE, CIRCLE, CIRCLE, CIRCLE, CIRCLE}, 
    {CIRCLE, CIRCLE, CIRCLE, CIRCLE, CIRCLE}, 
    {SQUARE, SQUARE, SQUARE, SQUARE, SQUARE}, 
    {TRIANGLE, TRIANGLE, TRIANGLE, TRIANGLE, TRIANGLE}, 
    {TRIANGLE, TRIANGLE, TRIANGLE, TRIANGLE, TRIANGLE}, 
};

我的 valgrind 输出:

==11706== Invalid write of size 1
==11706==    at 0x343040: _platform_memmove$VARIANT$Nehalem (in /usr/lib/system/libsystem_platform.dylib)
==11706==    by 0x1547E2: stpcpy (in /usr/lib/system/libsystem_c.dylib)
==11706==    by 0x1C2A43: __strcpy_chk (in /usr/lib/system/libsystem_c.dylib)
==11706==    by 0x1000013CD: play (game.c:21)
==11706==    by 0x1000012EF: main (starter.c:63)
==11706==  Address 0x104000001 is not stack'd, malloc'd or (recently) free'd
==11706==
==11706==
==11706== Process terminating with default action of signal 11 (SIGSEGV)
==11706==  Access not within mapped region at address 0x104000001
==11706==    at 0x343040: _platform_memmove$VARIANT$Nehalem (in /usr/lib/system/libsystem_platform.dylib)
==11706==    by 0x1547E2: stpcpy (in /usr/lib/system/libsystem_c.dylib)
==11706==    by 0x1C2A43: __strcpy_chk (in /usr/lib/system/libsystem_c.dylib)
==11706==    by 0x1000013CD: play (game.c:21)
==11706==    by 0x1000012EF: main (starter.c:63)
==11706==  If you believe this happened as a result of a stack
==11706==  overflow in your program's main thread (unlikely but
==11706==  possible), you can try to increase the size of the
==11706==  main thread stack using the --main-stacksize= flag.
==11706==  The main thread stack size used in this run was 8388608.
==11706==
==11706== HEAP SUMMARY:
==11706==     in use at exit: 33,497 bytes in 377 blocks
==11706==   total heap usage: 455 allocs, 78 frees, 39,513 bytes allocated
==11706==
==11706== LEAK SUMMARY:
==11706==    definitely lost: 0 bytes in 0 blocks
==11706==    indirectly lost: 0 bytes in 0 blocks
==11706==      possibly lost: 0 bytes in 0 blocks
==11706==    still reachable: 8,192 bytes in 2 blocks
==11706==         suppressed: 25,305 bytes in 375 blocks
==11706== Rerun with --leak-check=full to see details of leaked memory
==11706==
==11706== For counts of detected and suppressed errors, rerun with: -v
==11706== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 133 from 34)
Segmentation fault: 11

很抱歉没有提供可编译的示例,或遗漏任何相关信息,如果我需要提供任何其他内容以使任何事情更清楚,请发表评论!

知道这里发生了什么吗?

谢谢!

【问题讨论】:

  • 您是否确保为“结构结果”分配了内存。 IE。到“final_res”?
  • 我只是在starter.c 文件的顶部将它声明为struct result current_game;(传递到final_res arg),虽然我确实使用过malloc,虽然我无法得到它可以在不将 current_game 声明为指针的情况下工作
  • 你到底是怎么通过的?你应该通过它的引用,即play(p1, p2, &amp;your_local_struct);
  • 是的,我就是这样做的。由于我上面所说的原因,最终没有使用 malloc,所以它只是在文件顶部声明(我没有为它分配任何东西)并传递给play() func。这可能是问题所在吗?
  • for(i=0; i &lt; WIDTH; i++)??不应该for(i=0; i &lt; HEIGHT; i++)

标签: c memory valgrind memcpy strcpy


【解决方案1】:

这段代码不对:

void intialize(enum icons board[][WIDTH])
{
    int i, j;

    for(i=0; i < WIDTH; i++) {
        for(j=0; j < WIDTH; j++) {
            memcpy(&board[i][j], &master[i][j], WIDTH-1);
        }
    }
}

board[i][j] 的类型是 enum icons。使用memcpy时,需要使用sizeof(enum icons)而不是WIDTH-1

你可以通过两种方式解决这个问题。

  1. 将值从master 分配给board 一次一个元素。

    void intialize(enum icons board[][WIDTH])
    {
       int i, j;
    
       for(i=0; i < WIDTH; i++) {
          for(j=0; j < WIDTH; j++) {
             board[i][j] = master[i][j];
          }
       }
    }
    

  2. 使用memcpy 将数据行从master 复制到board

    void intialize(enum icons board[][WIDTH])
    {
       int i;
    
       for(i=0; i < WIDTH; i++) {
          // Copy WIDTH enum icons from master to board.
          memcpy(board[i], master[i], sizeof(enum icons)*WIDTH);
       }
    }
    

【讨论】:

  • 做到了!非常感谢!
  • @user3773076,不客气。很高兴它成功了。
【解决方案2】:

我认为问题出在你的初始化例程中: 您遍历所有字段(行和列)并复制完整的行而不是单个元素。当您达到索引的上限时,您复制的内容超出了数组的限制。

【讨论】:

    【解决方案3】:

    初始化时的 memcpy 是错误。第三个参数应该是 sizeof(master) 而不是 width-1。这假设数组 1 中元素的大小与 master(数组 2)中的元素大小相同

    【讨论】:

      猜你喜欢
      • 2019-03-07
      • 2018-07-28
      • 1970-01-01
      • 2012-12-03
      • 1970-01-01
      • 2016-09-05
      • 2017-03-12
      • 2014-07-01
      • 2011-11-22
      相关资源
      最近更新 更多