动态创建的数组大小不匹配

Size of array created dynamically doesn't match

本文关键字:不匹配 数组 创建 动态      更新时间:2023-10-16

我想我在那里错过了一些简单的东西,但我不明白为什么我会收到此错误。

我有一个包含原始数据的数组,我想转换为双精度。我也有这个数组的大小:

resWavFile0.resampledSingalData // array with data
resWavFile0.length // size of my array

如果我想显示它,那么它可以工作:

for (int i = 0; i < resWavFile0.length; i++) 
{
    cout << "n" << *((int*)resWavFile0.resampledSingalData+i) / (double)0x7fffffff;
}

完全没有崩溃,我的所有值都以双倍显示。但是现在我想将这些值保存在单独的数组中,所以我创建了:

double* singnalToProcess0;

而且因为 resWavFile0.length 可能会改变,我需要动态分配我的数组:

singnalToProcess0 = (double*) malloc(resWavFile0.length * sizeof(double));

我还可以将每个内存块的值设置为 0:

memset(singnalToProcess0, 0, resWavFile0.length * sizeof(double));

但现在我想把我的双打去:

for (int i = 0; i < resWavFile0.length; i++) 
{
    *(singnalToProcess0 + i) = *((int*)resWavFile0.resampledSingalData+i) / (double)0x7fffffff;
}

例如,我的 resWavFile0.length 值是 149077,但我在 i = 75074 时得到"0xC0000005:访问违规读取位置 0x01f6d000)。例如,如果我尝试在 malloc 中扩展数组的大小,即使像这样:

singnalToProcess0 = (double*) malloc( 30* resWavFile0.length * sizeof(double));

我在 75074 仍然收到相同的错误。如果我使用其他示例,例如更短或更长 - 它总是在迭代中间附近崩溃并出现此错误。静态分配也不起作用:

double* singnalToProcess0 = new double[149077];

也在中间附近崩溃 - 在 i = 75074...

那里的完整代码:

//// transfer to double
singnalToProcess0 = (double*) malloc(resWavFile0.length * sizeof(double));
memset(singnalToProcess0, 0, resWavFile0.length * sizeof(double));
for (int i = 0; i < resWavFile0.length; i++) {
    *(singnalToProcess0 + i) = *((int*)resWavFile0.resampledSingalData+i) / (double)0x7fffffff;
}

我做错了什么?

编辑:重采样瓦夫文件结构:

typedef struct ResampledWavFile
{
    short* resampledSingalData;
    int length;
} ResampledWavFile;

编辑2现在它可以工作了:

for (int i = 0; i < resWavFile0.length; i++)
{
    singnalToProcess0[i] = resWavFile0.resampledSignalData[i] / (double)0x7fffffff;
}

编辑3:我错了,这也是可能的:

singnalToProcess0 = new double[resWavFile0.length];
您可能

已经注意到,崩溃的索引非常接近数组的一半。这并非巧合,因为您遇到的问题是由于您将短裤数组(通常为 2 字节长)转换为整数数组(通常为 4 字节长)。像这样重写你的代码,它会起作用:

for (int i = 0; i < resWavFile0.length; i++) {
    *(singnalToProcess0 + i) = *((short*)resWavFile0.resampledSingalData+i) / (double)0x7fffffff; 
}

或完全去除铸件(去除(short*)),因为它实际上不是必需的。

另外,您在评论中提到,您不能使用new,因为您的数据具有动态大小。这也是不准确的,你总是可以用new代替C++malloc,通常应该这样做。

考虑struct ResampledWavFile的定义

typedef struct ResampledWavFile
{
    short* resampledSingalData;
    int length;
} ResampledWavFile;

并假设该类型的对象在resampledSingalData中具有lengthshort s,则行

for (int i = 0; i < resWavFile0.length; i++) 
{
    cout << "n" << *((int*)resWavFile0.resampledSingalData+i) / (double)0x7fffffff;
}

看起来不对劲。

表达式

*((int*)resWavFile0.resampledSingalData+i)

相当于

int* ip = (int*)resWavFile0.resampledSingalData;
*(ip+i)

这将访问越界内存,除非在您的平台中sizeof(short) == sizeof(int)内存。

如果将for循环中的行更改为:

    short num = resWavFile0.resampledSingalData[i];
    cout << "n" << num / (double)0x7fffffff;

您可以避免该问题。但是,我不明白这将如何影响您的数值计算的准确性。

问题的答案取决于你真正要做什么。您还没有解释清楚,但似乎有几种可能性,具体取决于resWavFile0.resampledSingalData数组的语义和resWavFile0.length值。只有你知道语义,我们在这里不是心灵感应或千里眼。

可能的解释包括(假设sizeof(int) == sizeof(short) * 2

  1. resWavFile0.resampledSingalData声明为 short 元素的数组。如果这些short元素是你的值,并且resWavFile0.length包含数组的长度,那么你所需要的只是

    for (int i = 0; i < resWavFile0.length; i++)
      singnalToProcess0[i] = 
        resWavFile0.resampledSignalData[i] / (double) 0x7fffffff;
    
  2. 如果resWavFile0.resampledSingalData应该被重新解释为一个int值的数组(每个值由两个连续的短线组成),但resWavFile0.length包含short数组的长度,那么resWavFile0.length应该是偶数的,你需要的是

    assert(resWavFile0.length % 2 == 0);
    for (int i = 0; i < resWavFile0.length / 2; i++)
      singnalToProcess0[i] = 
        ((int *) resWavFile0.resampledSignalData[i]) / (double) 0x7fffffff;
    
  3. 如果resWavFile0.resampledSingalData应该被重新解释为一个int值的数组(每个值由两个连续的短resWavFile0.length组成),并且包含该int数组的长度,那么你需要的是

    for (int i = 0; i < resWavFile0.length; i++)
      singnalToProcess0[i] = 
        ((int *) resWavFile0.resampledSignalData[i]) / (double) 0x7fffffff;
    

    但这与您的原始变体相同,它正在崩溃,因此显然这种解释是不正确的。

doubleintshort在内存中的大小不同。由于对齐和其他内存访问内容,使用内存增量(如 *(singnalToProcess0 + i))进行访问不会获得您想要的结果。您应该像访问常规数组一样访问它们:singnalToProcess0[i] = ... .这同样应该适用于转向resWavFile0.resampledSingalData[i] *((int*)resWavFile0.resampledSingalData+i)