动态创建的数组大小不匹配
Size of array created dynamically doesn't match
我想我遗漏了一些简单的东西,但我不明白为什么会出现这个错误。
我有一个数组,其中包含要转换为双精度的原始数据。我也有这个数组的大小:
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 但我得到“0xC0000005:访问冲突读取位置 0x01f6d000) 在 i = 75074。如果我尝试在 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;
}
我做错了什么?
编辑:
重新采样的 WavFile 结构:
typedef struct ResampledWavFile
{
short* resampledSingalData;
int length;
} ResampledWavFile;
Edit2 现在可以使用了:
for (int i = 0; i < resWavFile0.length; i++)
{
singnalToProcess0[i] = resWavFile0.resampledSignalData[i] / (double)0x7fffffff;
}
Edit3:我错了,这也是可能的:
singnalToProcess0 = new double[resWavFile0.length];
double
、int
、short
在内存中的大小不同。由于对齐问题和其他内存访问问题,使用 *(singnalToProcess0 + i)
之类的内存增量访问无法获得您想要的结果。
您应该像访问常规数组一样访问它们:singnalToProcess0[i] = ...
。同样应该应用于 *((int*)resWavFile0.resampledSingalData+i)
以转向 resWavFile0.resampledSingalData[i]
.
您可能已经注意到崩溃的索引非常接近数组的一半。这并非巧合,因为您遇到的问题是由于您将短裤数组(通常为 2 个字节长)转换为一个整数数组(通常为 4 个字节长)。像这样重写你的代码,它会起作用:
for (int i = 0; i < resWavFile0.length; i++) {
*(singnalToProcess0 + i) = *((short*)resWavFile0.resampledSingalData+i) / (double)0x7fffffff;
}
或完全删除转换(删除(short*)
),因为实际上并不需要。
此外,您在评论中提到,您不能使用 new
,因为您的数据具有动态大小。它也不准确,在 C++ 中你总是可以使用 new
代替 malloc
,通常应该这样做。
考虑 struct ResampledWavFile
的定义
typedef struct ResampledWavFile
{
short* resampledSingalData;
int length;
} ResampledWavFile;
并假设该类型的对象在 resampledSingalData
中有 length
个 short
,行
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
)
resWavFile0.resampledSingalData
声明为 short
个元素的数组。如果这些 short
元素是您的值并且 resWavFile0.length
包含数组的长度,那么您只需要
for (int i = 0; i < resWavFile0.length; i++)
singnalToProcess0[i] =
resWavFile0.resampledSignalData[i] / (double) 0x7fffffff;
如果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;
如果 resWavFile0.resampledSingalData
应该被重新解释为 int
值的数组(每个由两个连续的短裤组成)并且 resWavFile0.length
包含该长度int
数组,那么你需要的是
for (int i = 0; i < resWavFile0.length; i++)
singnalToProcess0[i] =
((int *) resWavFile0.resampledSignalData[i]) / (double) 0x7fffffff;
但这与您的原始变体相同,它正在崩溃,因此显然这种解释是不正确的。
我想我遗漏了一些简单的东西,但我不明白为什么会出现这个错误。
我有一个数组,其中包含要转换为双精度的原始数据。我也有这个数组的大小:
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 但我得到“0xC0000005:访问冲突读取位置 0x01f6d000) 在 i = 75074。如果我尝试在 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;
}
我做错了什么?
编辑: 重新采样的 WavFile 结构:
typedef struct ResampledWavFile
{
short* resampledSingalData;
int length;
} ResampledWavFile;
Edit2 现在可以使用了:
for (int i = 0; i < resWavFile0.length; i++)
{
singnalToProcess0[i] = resWavFile0.resampledSignalData[i] / (double)0x7fffffff;
}
Edit3:我错了,这也是可能的:
singnalToProcess0 = new double[resWavFile0.length];
double
、int
、short
在内存中的大小不同。由于对齐问题和其他内存访问问题,使用 *(singnalToProcess0 + i)
之类的内存增量访问无法获得您想要的结果。
您应该像访问常规数组一样访问它们:singnalToProcess0[i] = ...
。同样应该应用于 *((int*)resWavFile0.resampledSingalData+i)
以转向 resWavFile0.resampledSingalData[i]
.
您可能已经注意到崩溃的索引非常接近数组的一半。这并非巧合,因为您遇到的问题是由于您将短裤数组(通常为 2 个字节长)转换为一个整数数组(通常为 4 个字节长)。像这样重写你的代码,它会起作用:
for (int i = 0; i < resWavFile0.length; i++) {
*(singnalToProcess0 + i) = *((short*)resWavFile0.resampledSingalData+i) / (double)0x7fffffff;
}
或完全删除转换(删除(short*)
),因为实际上并不需要。
此外,您在评论中提到,您不能使用 new
,因为您的数据具有动态大小。它也不准确,在 C++ 中你总是可以使用 new
代替 malloc
,通常应该这样做。
考虑 struct ResampledWavFile
typedef struct ResampledWavFile
{
short* resampledSingalData;
int length;
} ResampledWavFile;
并假设该类型的对象在 resampledSingalData
中有 length
个 short
,行
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
)
resWavFile0.resampledSingalData
声明为short
个元素的数组。如果这些short
元素是您的值并且resWavFile0.length
包含数组的长度,那么您只需要for (int i = 0; i < resWavFile0.length; i++) singnalToProcess0[i] = resWavFile0.resampledSignalData[i] / (double) 0x7fffffff;
如果
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;
如果
resWavFile0.resampledSingalData
应该被重新解释为int
值的数组(每个由两个连续的短裤组成)并且resWavFile0.length
包含该长度int
数组,那么你需要的是for (int i = 0; i < resWavFile0.length; i++) singnalToProcess0[i] = ((int *) resWavFile0.resampledSignalData[i]) / (double) 0x7fffffff;
但这与您的原始变体相同,它正在崩溃,因此显然这种解释是不正确的。