我想我在那里错过了一些简单的东西,但我不明白为什么我会收到此错误。
我有一个包含原始数据的数组,我想转换为双精度。我也有这个数组的大小:
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
中具有length
个short
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
)
-
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;
但这与您的原始变体相同,它正在崩溃,因此显然这种解释是不正确的。
double
、int
、short
在内存中的大小不同。由于对齐和其他内存访问内容,使用内存增量(如 *(singnalToProcess0 + i)
)进行访问不会获得您想要的结果。您应该像访问常规数组一样访问它们:singnalToProcess0[i] = ...
.这同样应该适用于转向resWavFile0.resampledSingalData[i]
*((int*)resWavFile0.resampledSingalData+i)
。