这个问题的目的是提供一个关于如何在C中动态正确分配多维数组的参考.这是一个经常被误解的主题,即使在一些C编程书籍中也很难解释.因此,即使是经验丰富的C程序员也很难做到正确.
我从编程教师/书籍/教程中了解到,动态分配多维数组的正确方法是使用指针指针.
然而,SO上的几个高代表用户现在告诉我这是错误和不好的做法.他们说指针到指针不是数组,我实际上并没有分配数组,而且我的代码不必要地慢.
这就是我教我分配多维数组的方法:
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
int** arr_alloc (size_t x, size_t y)
{
  int** pp = malloc(sizeof(*pp) * x);
  assert(pp != NULL);
  for(size_t i=0; i<x; i++)
  {
    pp[i] = malloc(sizeof(**pp) * y);
    assert(pp[i] != NULL);
  }
  return pp;
}
int** arr_fill (int** pp, size_t x, size_t y)
{
  for(size_t i=0; i<x; i++)
  {
    for(size_t j=0; j<y; j++)
    {
      pp[i][j] = (int)j + 1;
    }
  }
  return pp;
}
void arr_print (int** pp, size_t x, size_t y) …c arrays dynamic-arrays dynamic-allocation variable-length-array
我是C++编程的新手,但长期以来一直在使用C和Java.我正在尝试在我正在处理的某些串行协议中执行类似接口的层次结构,并不断收到错误:
Undefined reference to 'operator delete(void*)'
(简化)代码如下:
PacketWriter.h:
class PacketWriter {
public:
    virtual ~PacketWriter() {}
    virtual uint8_t nextByte() = 0;
}
StringWriter.h:
class StringWriter : public PacketWriter {
public:
    StringWriter(const char* message);
    virtual uint8_t nextByte();
}
构造函数和nextByte函数在StringWriter.cpp中实现,但没有别的.我需要能够从指向PacketWriter的指针中删除StringWriter,如果我为StringWriter定义了一个析构函数,我是否已经得到了各种其他类似的错误.我敢肯定这是一个简单的问题,我作为一个新手忽略了.
另外,我正在为AVR芯片编写这个,在Windows上使用avr-g ++.
谢谢
自从我们的用户从Excel 2007升级到32位Excel 2013以来,我们公司面临着大量的性能和稳定性问题.
我们不得不为某些用户禁用硬件加速,更改控制面板\轻松访问中心的设置,甚至升级英特尔图形驱动程序以提高稳定性,所有这些都取得了不同程度的成功.
但是我们无法解决的一个问题是:
32位版本的Excel 2013似乎使用自己的内存管理器从32位内存映射到Windows 7使用的64位内存.
问题是,当这个内存变得过于分散时,Excel 2013将完全崩溃.
有时,经过一个小时的使用后,我们看到Excel 2013尝试搜索一块XX'Mb的内存块,如果它找不到这个大小的连续内存块,它就会崩溃.
作为一家金融公司,我们在这些Excel文件中有很多传统的VBA代码,而迁移到64位Excel 2013会引入更多问题.
那么有谁知道如何使用Excel 2013修复内存问题..?
更新
一些读者(可以理解)问我们为什么不安装64位版本的Excel 2013,特别是因为我们运行的是64位Windows 7.
引用微软的原因是兼容性.
"我们建议大多数用户使用32位版本的Office,因为它与大多数其他应用程序(尤其是第三方加载项)更兼容.这就是为什么默认安装32位版本的Office 2013,即使在64位Windows操作系统."
我们的用户不需要花哨,口哨或时髦的动画.即使使用10年前编写的Excel文件和VBA,他们也想要一些稳定的东西.其中一些代码甚至使用FORTRAN .dll计算引擎,DAO库等.
从IT支持的角度来看,我们只需要一个仍然受Microsoft支持的Excel版本.
这就是为什么我们现在使用的是32位Excel 2013.
问题是,这是32位Excel 2013的一个令人讨厌的问题,大多数金融公司仍然在传统的Excel/Access应用程序上大量供应......我们可以做些什么来使这个环境更稳定?
我应该担心std :: vector的内存碎片吗?如果是这样,有没有办法帮助防止它?我并不总是预测我的程序在PC上运行,它们也可能在嵌入式设备/游戏机上运行,所以我不能总是依赖虚拟内存.
然后我再次相信使用动态大小的数组而不是静态数组会更有效,因此只有在需要时才会分配内存.它还可以简化我的程序的设计过程.有没有办法有效地实现这一目标?
谢谢你的建议!
我正在从Learn C the Hard way在线课程中吸取教训.在下面的代码示例中,我不明白为什么这两个free()调用是必要的.我以为只需要拨打free()一次,因为只有一次malloc()发生.有人可以澄清我们为什么需要两个吗?
如果我发表评论free(who->name);然后valgrind告诉我,我已经失去了一大块记忆,就像这样;
LEAK SUMMARY:
definitely lost: 21 bytes in 2 blocks
这是代码:
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
struct Person {
    char *name;
    int age;
    int height;
    int weight;
};
struct Person *Person_create(char *name, int age, int height, int weight)
{
    struct Person *who = malloc(sizeof(struct Person));
    assert(who != NULL);
    who->name = strdup(name);
    who->age = age;
    who->height = height;
    who->weight = weight; …所以我有这个 C++ 程序,它基本上解析巨大的数据集文件并将内容加载到内存中的 hashmap 中(这部分在主线程中受到限制,所以它永远不会占用大量时间)。完成后,我将指针翻转到新的内存位置,并对旧的内存位置调用 delete。除此之外,程序通过在内存映射(在主线程上)中查找内容来进行传入请求匹配。假设那些巨大的地图被包裹在Evaluator类中:
Evaluator* oldEvaluator = mEvaluator;
Evaluator* newEvaluator = parseDataSet();
mEvaluator = newEvaluator;
delete oldEvaluator;
//And then on request processing:
mEvaluator.lookup(request)
映射可以包含数百万个字符串对象作为键。它们是常规字符串,可以是 ip、UserAgent 等请求属性,但每个字符串都是插入到 STL unordered_map 中的字符串对象。
数据集会定期更新,但大多数情况下,程序只是对内存中的数据集进行请求属性匹配,它很好,高效且没有错误,除非发生新数据集的批量消耗。使用这个大型数据集的另一种方法是使用流,但这是一个相对长期的解决方案。
它曾经是一个使用事件驱动模型的单线程程序,但是每次放置一个完整的新集合并调用销毁时,删除整个事物花费的时间太长,从而阻塞了请求处理。
所以我把这种地图的删除放到了一个单独的线程上。问题是现在删除和请求处理似乎同时发生,我可以看到请求处理线程非常明显,急剧放缓。
当然,主机上还有其他进程在运行,我确实希望这 2 个线程竞争 CPU 周期。但我没想到请求匹配线程会大幅放缓。平均而言,一个请求应该被处理 500us 级别,但是当删除线程正在运行时,它会慢到 5ms。有时 cpu 会中断匹配的线程(因为它花费的时间太长),它可能会持续 50 毫秒,或 120 毫秒等。在极端情况下,一个请求可能需要整个 1000 毫秒来处理,这大约是整个时间数据结构删除需要另一个线程。
了解这种减速的根本原因的最佳方法是什么?它更像是 CPU 还是内存带宽瓶颈?我想象着只要我把它放在一个单独的线程上,我就不会在乎它有多慢,因为它毕竟必须一个一个地删除字符串对象,所以我没想到它会影响另一个线程......
编辑:多亏了一些评论/答案似乎已经指出了几个可能的原因:
我正在编写一个基于 qt 的 c++ 应用程序,我需要能够检测内存碎片以检查当前系统是否能够真正承受内存负载:程序加载一个大图像(15/21 兆像素是标准)在内存中,然后对其执行一些过滤(使用稀疏矩阵)。例如,我在 Windows 中遇到内存碎片问题,VMMap 在这方面非常有帮助:问题是一些 DLL(Wacom 平板电脑“wintab32.dll”和 UltraMon 应用程序)没有重新定位,因此正在拆分地址空间在过程的 0x10000000-0x30000000 VA 处。
我想为应用程序提供对碎片问题的某种认识,并想知道是否已经存在提供 VMMAP 信息的跨平台 (linux/mac/win32) 方法。
我最近阅读了有关内存碎片的主题: 如何解决内存碎片和什么是内存碎片?
我想在这些文章中看到一些内存分配图,例如作者http://pavlovdotnet.wordpress.com/2007/11/10/memory-fragmentation/
你可以推荐一些工具来获取这样的内存分配映射,这样我就可以看到内存是否碎片化以及可用的最大可用空间是多少.
我在Windows上,所以我更喜欢在这个系统上工作的工具.
我知道有很多类似的问题都得到了公认的答案(这里,这里甚至这个),但到目前为止,我没有找到关于如何在不重新启动 R 会话的情况下释放一些内存空间的明确答案。
我知道,可以保存他的工作区,重新启动 R 并重新加载工作区,但是:
情况似乎并非如此。即使在删除了我工作区的一半最大对象(感谢这个很好的答案)并运行之后gc(),top仍然给我提供了完全相同的内存使用百分比。
这里的一个评论,它说:
R 的垃圾收集将 RAM 标记为可用。由您的操作系统来收回
听起来不错,但不确定这真的发生了。top即使在rm()和之后gc(),甚至在操作系统中启动新的其他进程之后,甚至在 2 小时、10 小时或 3 天之后,仍然向我显示 R 使用的相同数量的内存。
这个评论表明它必须查看加载的库和图形设备,但为什么呢?我该如何解决?
如果我rm()一个3GB对象然后gc()用来释放内存,R 怎么可能仍然使用相同百分比的内存?