【问题标题】:Different Unallocated Memory Behaviour Between Visual Studio VersionsVisual Studio 版本之间的不同未分配内存行为
【发布时间】:2012-05-20 02:22:31
【问题描述】:

我遇到了一个奇怪的情况。我正在尝试在我的相机管理软件中实现一个 10 多年前的 pci 相机设备 SDK。制造商不再营业,我没有机会获得官方帮助。所以我在这里,为我的丑陋问题寻求一些帮助。

SDK 附带Visual Studio 6.0 示例。其中一个包含文件的结构以单字节数组结尾,如下所示;

typedef struct AVData {
    ...  
    BYTE audioVideoData[1];
}AVDATA, *PAVDATA;

但是这个单字节分配的字节数组接收视频帧并且很奇怪,它适用于 Visual Studio 6.0 版本。如果我使用 Visual Studio 2005/2008/2010 尝试它,我会开始收到 Memory Access Violation 错误消息,这实际上是有道理的,因为以后不可能将空间分配给固定大小的数组,不是吗?但是相同的代码在 VS 6.0 上运行良好?!这可能是由编译器或 c++ 运行时差异引起的,但我在这个主题上不是很有经验,所以很难说出我的某些原因。

我尝试将大小更改为预期的最大字节数,如下所示;

typedef struct AVData {
    ...  
    BYTE audioVideoData[20000];
}AVDATA, *PAVDATA;

这有助于它开始工作,但有时我在尝试销毁库的解码器对象时遇到内存访问冲突问题。

这肯定有问题。我没有 SDK 的源代码,只有 DLL、Lib 和 Header 文件。我的问题是:

1) 在Visual Studio 6.0版本中给固定大小的数组分配空间真的合法吗?

2) 是否有任何可能的方法(编译器选项等)使相同的代码适用于较新的 VS 版本/C++ 运行时?

3) 由于我编辑头文件的解决方法在一定程度上可行,但仍然存在问题,您知道解决此问题的更好方法吗?

【问题讨论】:

  • 我想问题应该出在其他地方。数组大小在这里应该不是问题,它不是一个上限。
  • 但是为什么我们会得到内存访问冲突呢?如果我从这个结构创建一个新对象,它不会以 1 的大小创建(+ 其余结构元素)吗?那么,之后我们如何将多个字节存储到 audioVideoData 数组中呢?是否可以将内存重新分配给固定大小的数组?由于它适用于 VS 6.0 版本,因此可能更早,但 VS 2005+ 呢?
  • 您的问题是您没有正确分配这些结构。必须根据 cmets 和答案为它们分配 malloc。您需要重新访问此库的文档。
  • @David:问题是,即使是他们自己的 SDK 示例也会在新的 Visual Studio 版本中产生相同的错误。分配部分在 SDK 函数内部完成。这不取决于我。我正在尝试找到一个神奇的解决方法,到目前为止没有运气。

标签: c++ visual-studio visual-c++ memory-management compiler-errors


【解决方案1】:

IIRC 它是创建大小可变结构的老技巧。

考虑

struct {
  int len;
  char name[1];
} s;

如果完成了适当的分配,“名称”现在可以是可变长度的,它将按顺序排列在内存中:

char* foo = "abc";
int len = strlen(foo);

struct s* p = malloc( sizeof(int) + len + 1 );

p->len = len;
strcpy(p->name, foo );

我认为以上内容在较新版本的 Visual Studio 中也应该可以正常工作,也许这是一个打包问题,你有没有做过#pragma pack(1) 来获取字节边界上的结构?我知道 VS6 有默认设置。

【讨论】:

  • 即使你的回答并没有解决我的问题,包括 pragma 技巧,你的回答是正确的,我的问题目前似乎无法解决。
  • 如果我是你,我会尝试使用更大的缓冲区,自 10 年前以来发生了很多事情,尤其是速度。也许还有一些与结构无关的其他问题。如果增加缓冲区会减少内存访问错误,那么您可能会遇到一些计时错误。
【解决方案2】:

代码几乎肯定会在某些方面表现出未定义的行为,除了修复 SDK 的接口或源代码外,没有其他方法可以解决此问题。由于它不再营业,这是不可能的。

【讨论】:

  • 从技术上讲,你是对的——它是 UB。实际上,struct hack 已经足够常见了,以至于当你“正确”使用它时,获得意外结果的机会基本上是不存在的。自 C99 以来的大多数编译器都不太可能改变这一点,并且更新版本将其作为“灵活的数组成员”。
  • 我认为这个答案在上下文中没有意义。 “UB”消除了对任意编译器如何处理它的限制。但是我们知道这个库是用 VC6 编译的,永远不会用另一个编译器编译,所以行为已经一成不变。
【解决方案3】:

像这样的 C 结构中的单元素数组通常意味着直到运行时才知道大小。 (有关 Windows 示例,请参阅BITMAPINFO。)

通常,会有一些其他信息(可能在结构中)告诉您缓冲区需要多大。您永远不会直接分配其中之一,而是分配正确大小的内存块,然后进行转换:

int size = /* calculate frame size somehow */
AVDATA * data = (AVDATA*) malloc(sizeof(AVDATA) + size);
// use data->audioVideoData

【讨论】:

    猜你喜欢
    • 2020-07-06
    • 2018-02-25
    • 1970-01-01
    • 1970-01-01
    • 2017-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多