相关疑难解决方法(0)

free和malloc如何在C中工作?

我试图找出如果我试图从中间"释放"指针会发生什么,请看下面的代码:

char *ptr = (char*)malloc(10*sizeof(char));

for (char i=0 ; i<10 ; ++i)
{
    ptr[i] = i+10;
}
++ptr;
++ptr;
++ptr;
++ptr;
free(ptr);
Run Code Online (Sandbox Code Playgroud)

我收到一个崩溃,出现未处理的异常错误消息.我想了解为什么以及如何免费工作,这样我不仅知道如何使用它,而且还能够理解奇怪的错误和异常并更好地调试我的代码ץ

非常感谢

c memory malloc free

58
推荐指数
6
解决办法
7万
查看次数

C内存分配器和严格别名

即使在阅读了相当多的严格别名规则后,我仍然感到困惑.据我所知,不可能实现遵循这些规则的合理的内存分配器,因为malloc永远不能重用释放的内存,因为内存可以用于在每次分配时存储不同的类型.

显然这不可能是正确的.我错过了什么?如何实现遵循严格别名的分配器(或内存池)?

谢谢.

编辑:让我用一个愚蠢的简单例子来澄清我的问题:

// s == 0 frees the pool
void *my_custom_allocator(size_t s) {
    static void *pool = malloc(1000);
    static int in_use = FALSE;
    if( in_use || s > 1000 ) return NULL;
    if( s == 0 ) {
        in_use = FALSE;
        return NULL;
    }
    in_use = TRUE;
    return pool;
}

main() {
    int *i = my_custom_allocator(sizeof(int));
    //use int
    my_custom_allocator(0);
    float *f = my_custom_allocator(sizeof(float)); //not allowed...
}
Run Code Online (Sandbox Code Playgroud)

c memory-management strict-aliasing language-lawyer

8
推荐指数
1
解决办法
2472
查看次数

C/C++严格别名,对象生命周期和现代编译器

我面临着关于C++严格别名规则及其可能含义的困惑.请考虑以下代码:

int main() {
  int32_t a = 5;
  float* f = (float*)(&a);
  *f = 1.0f;

  int32_t b = a;   // Probably not well-defined?
  float g = *f;    // What about this?
}
Run Code Online (Sandbox Code Playgroud)

看看C++规范,3.10.10节,从技术上讲,没有一个给定的代码似乎违反了给定的"别名规则":

如果程序试图通过以下类型之一以外的左值访问对象的存储值,则行为未定义:
...合格的访问者类型列表...

  • *f = 1.0f;不会违反规则,因为无法访问存储的值,即我只是通过指针写入内存.我不是从记忆中读书或试图在这里解释一个值.
  • 该行int32_t b = a;不违反规则,因为我通过其原始类型进行访问.
  • float g = *f;出于同样的原因,这条线并没有违反规则.

另一个线程中,成员CortAmmon实际上在响应中提出了相同的点,并且添加了通过写入活动对象而产生的任何可能的未定义行为,如 *f = 1.0f;将在标准的"对象生存期"定义(似乎是对于POD类型来说是微不足道的).

但是:互联网上有大量证据表明上述代码将在现代编译器上产生UB.例如,见这里这里.
在大多数情况下,论证是编译器可以自由考虑&a,f而不是相互混叠,因此可以自由重新安排指令.

现在最大的问题是,如果这种编译器行为实际上是对标准的"过度解释".
唯一一次标准谈论"混叠"的唯一一次是在3.10.10的脚注中,其中明确指出那些是控制混叠的规则.
正如我之前提到的,我没有看到任何上述代码违反了标准,但是很多人(可能还有编译人员)认为它是非法的.

我真的很感激这里的一些澄清.

小更新:
正如成员BenVoigt指出的那样,int32_t …

c++ memory compiler-construction strict-aliasing type-punning

8
推荐指数
1
解决办法
555
查看次数

如何推理类似 malloc 的函数的严格别名

AFAIK,在三种情况下可以使用别名

  1. 仅限定符或符号不同的类型可以相互别名。
  2. 结构或联合类型可以为其中包含的类型指定别名。
  3. 将 T* 转换为 char* 就可以了。(不允许相反)

在阅读John Regehrs 博客文章中的简单示例时,这些是有意义的,但我不确定如何推理较大示例(例如类似 malloc 的内存安排)的别名正确性。

我正在阅读Per Vognsens 重新实现Sean Barrets弹性缓冲区。它使用类似 malloc 的模式,其中缓冲区在其前面具有关联的元数据。

typedef struct BufHdr {
    size_t len;
    size_t cap;
    char buf[];
} BufHdr;
Run Code Online (Sandbox Code Playgroud)

通过从指针减去偏移量来访问元数据b

#define buf__hdr(b) ((BufHdr *)((char *)(b) - offsetof(BufHdr, buf)))
Run Code Online (Sandbox Code Playgroud)

这是原始buf__grow函数的一个稍微简化的版本,它扩展了缓冲区并将 buf 作为void*.

void *buf__grow(const void *buf, size_t new_size) { 
     // ...  
     BufHdr *new_hdr;  // (1)
     if (buf) {
         new_hdr = xrealloc(buf__hdr(buf), new_size);
     } else {
         new_hdr = xmalloc(new_size); …
Run Code Online (Sandbox Code Playgroud)

c strict-aliasing

5
推荐指数
1
解决办法
941
查看次数