0

Ok, I was trying to implement memmove just as a programming exercise, and I get a memory access violation in the memmove function when I try to use malloc. Here is the function:

//Start

void* MYmemmove (void* destination, const void* source, size_t num) { 

    int* midbuf = (int *) malloc(num); // This is where the access violation happens.
    int* refdes = (int *) destination; // A pointer to destination, except it is casted to int*
    int* refsrc = (int *) source; // Same, except with source
    for (int i = 0;num >= i;i++) { 
        midbuf[i] = *(refsrc + i); // Copy source to midbuf
    }
    for (int i = 0;num >= i;i++) { 
        refdes[i] = *(midbuf + i); // Copy midbuf to destination
    } 
    free(midbuf); // free midbuf 
    refdes = NULL; // Make refdes not point to destination anymore
    refsrc = NULL; // Make refsrc not point to source anymore
    return destination;
}

By the way, I am sort of a newbie to pointers, so don't be suprised if there is some mistakes. What am I doing wrong?

4

7 回答 7

4

请注意其他建议!答案取决于您的 memmove 将如何使用。其他答案表明您应该更改 malloc 调用以考虑 int 的大小。但是,如果您的 memmove 函数将用于表示“移动此字节数”,那么实现将是错误的。我会改为使用 char* ,因为它可以一次性解决几个问题。

此外,anint通常为 4 个字节,char通常为 1 个字节。如果void*您收到的地址不是字对齐的(不是 4 字节的倍数),您将遇到问题:要复制一个非字对齐的 int,您将不得不进行多次读取和昂贵的位掩码。这是低效的。

最后,内存访问冲突发生了,因为您每次都在增加 midbufint指针,并且一次向前移动4 个字节。但是,您只分配了 num bytes,因此最终会尝试访问超出分配区域的末尾。

/** Moves num bytes(!) from source to destination */
void* MYmemmove (void* destination, const void* source, size_t num) { 

    // transfer buffer to account for memory aliasing
    // http://en.wikipedia.org/wiki/Aliasing_%28computing%29
    char * midbuf = (char *) malloc(num); // malloc allocates in bytes(!)
    char * refdes = (char *) destination;
    char * refsrc = (char *) source;

    for (int i = 0; i < num; i++) { 
        midbuf[i] = *(refsrc + i); // Copy source to midbuf
    }

    for (int i = 0; i < num; i++) { 
        refdes[i] = *(midbuf + i); // Copy midbuf to destination
    } 

    free(midbuf); // free midbuf
    // no need to set the pointers to NULL here.
    return destination;
}

通过逐字节复制,我们避免了对齐问题,以及 num 本身可能不是 4 个字节的倍数的情况(例如 3,因此 int 对于该移动来说太大了)。

于 2012-10-07T18:01:56.753 回答
3

Replace the string with malloc with this one:

int* midbuf = (int *) malloc(num*sizeof(int)); 

The problem is that you allocated not num elements of int but num bytes.

于 2012-10-07T17:54:05.703 回答
1
int* midbuf = (int *) malloc(num); // This is where the access violation happens.
int* refdes = (int *) destination; // A pointer to destination, except it is casted to int*
int* refsrc = (int *) source; // Same, except with source
for (int i = 0;num >= i;i++) { 
    midbuf[i] = *(refsrc + i); // Copy source to midbuf
}

You malloc only num bytes, but in the loop, you try to copy num ints. Since an int usually takes more than one byte, you're accessing out of bounds.

于 2012-10-07T17:54:26.490 回答
0

memory access violation?

You are trying to access memory you are not entitled to access. Maybe you have a null pointer or the pointer is pointing into another program or the code segment.

于 2012-10-07T17:54:04.523 回答
0

The problem is that you're mallocing num bytes into midbuf, and then copying num ints into it. Since an int is larger than a byte on most platforms, you have a problem. Change your malloc to num*sizeof(int) and you won't have that problem.

于 2012-10-07T17:55:00.933 回答
0

有两个问题需要看

1. 内存空间

(前提是按照问题建议MYmemmove进行自定义实现移动)ints

    int* midbuf = (int *) malloc(num * sizeof(int));

malloc是基于字节的,将分配num个字节。int *是指向 的指针ints。意思midbuf[x]是将从中访问内存midbuf + sizeof(int)*x。您想分配num ints(int 的大小取决于体系结构,通常为 4 或 2 个字节)。因此malloc(num * sizeof(int)).

2.数组索引

    for (int i = 0;num > i;i++) { 

在 C(和 C++)中,数组是从 0 开始的,即第一个索引是0. 你做对了。但这也意味着如果你保留num ints,可用的索引将是 from 0to num-1。在您的循环中,由于 condition 的原因,i它将从0to变化,这意味着您将访问项目。所以(或)会是一个更好的条件。numnum >= inum+1num > ii < numfor

于 2012-10-07T18:06:33.897 回答
-1
#include <stdlib.h>  // did you included this?


void* MYmemmove (void* destination, const void* source, size_t num) { 

    char *Source = source, *Destination = destination;
    char *Middle = malloc( sizeof(char) * num );    // midbuf

    for (int i = 0; i < num ; i++) { 
        Middle[i] = Destination[i]; // Copy source to midbuf
    }
    for (int i = 0; i < num ; i++) { 
        Destination[i] = Middle[i]; // Copy midbuf to destination
    }

    free(Middle);                   // free memory allocated previously with malloc
    return destination;
}

可能会发生访问冲突,因为您没有包含 malloc 所需的库(如果您忘记了函数定义,标准 c 不会在您的脸上抛出错误)。您不需要将指针标记为 NULL,因为 C 中没有垃圾收集(指针就是这样 - 指针。指向内存中某个点的地址,而不是内存本身)。

想想像这样的指针

指针地址 0x1243 0x4221 目的地 -> {某种数据}

Destination = 0x1243 *Destination = 当前地址 0x4221 处的任何值

您也不能索引 void 指针。您必须首先将它们转换为某种类型,以便编译器知道它们需要多少偏移量。

目的地[x] = *(目的地+x)

char 是 1 个字节,所以 char 指针实际上会移动 x 个字节,但 int 是 4 个字节,而 int 指针将移动 4*x 个字节。如果这听起来很技术性,请不要太担心,当您达到非常低的水平时,它会很重要;)

于 2012-10-07T18:01:53.697 回答