2015-03-10 2 views
-1

Я думаю, что мне не хватает чего-то простого, но я не могу понять, почему я получаю эту ошибку.Размер массива, созданного динамически, не соответствует

У меня есть массив с необработанными данными, которые я хочу преобразовать в double. У меня также есть размер этого массива:

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) при г = 75074. Если я пытаюсь расширить размер массива в таНос, например, даже так:

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

Я по-прежнему получаю такую ​​же ошибку при 75074. Если я работаю с другим образцом, например, короче или дольше - он всегда вылетает с этой ошибкой вблизи середины итерации. Также статическое распределение не работает:

double* singnalToProcess0 = new double[149077]; 

врезаться Также около середины - при я = 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; 
} 

Что я делаю неправильно?

Edit: ResampledWavFile структура:

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]; 
+0

Какой тип resWavFile0? Можете ли вы показать фрагмент кода его объявления? – Alejandro

+3

Если вы используете 'malloc()', вы не должны использовать C++. Если вы используете C++, вы должны использовать 'new'. Пожалуйста, выберите язык - один язык - потому что разумные ответы очень разные в зависимости от того, код вы на C или C++. (Да, вы, вероятно, можете сделать код работать в обоих, вы, вероятно, не должны.) –

+0

Я использую C++, но я не могу использовать new, потому что resWavFile0.length - это вычисленное значение. Я также добавил структуру ResampledWavFile в соответствии с запросом. Код о заполнении массива довольно длинный, потому что его метод передискретизации с низким уровнем интеллекта lvl intel - но если я попытаюсь отобразить значения внутри resampledSignalData и длины, я могу получить доступ к каждому из них. – F1sher

ответ

2

Возможно, вы заметили, что индекс, с которым вы сталкиваетесь, очень близок к половине вашего массива.Это неслучайно, потому что проблема, с которой вы сталкиваетесь, связана с тем, что вы накладываете свой массив шорт (обычно 2 байта) на массив из int (обычно 4 байта). Перепишите код, как это, и он будет работать:

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

Или полностью удалить литье (удалить (short*)), так как она на самом деле не нужна.

Кроме того, вы упомянули в комментариях, что вы не можете использовать new, потому что ваши данные имеют динамический размер. Это также неточно, вы всегда можете использовать new вместо malloc на C++ и обычно должны это делать.

+0

Это правда. Я очень удивлен, поскольку у меня была проблема с использованием 'new' несколько дней назад где-то. 'singnalToProcess0 = новый double [resWavFile0.length];' работает. – F1sher

+0

Кроме того, не забудьте «удалить [] signalToProcess0' после того, как вы закончите с ним. – Ishamael

+0

@ F1sher: Итак, если вам действительно не нужен этот приведение к 'int *' с правой стороны, почему вы утверждаете, что ваш цикл 'cout << ...' работал правильно? Нет никакого способа, чтобы он мог работать должным образом, если это приведение к 'int *' было необоснованным. – AnT

-3

double, int , short не являются такого же размера в памяти. Доступ с увеличением объема памяти, например *(singnalToProcess0 + i), не получает желаемых результатов из-за элементов выравнивания и других материалов доступа к памяти. Вы должны получить к ним доступ, как обычные массивы: singnalToProcess0[i] = .... То же самое следует применить к *((int*)resWavFile0.resampledSingalData+i), чтобы перейти на resWavFile0.resampledSingalData[i].

+0

signalToProcess0 [i] является просто синтаксическим сахаром для * (singnalToProcess0 + i) – Ishamael

+0

Не для каждого типа из-за размера типа –

+0

@G. Ko: Во-первых, нет никакой разницы между 'singnalToProcess0 [i]' и '* (singnalToProcess0 + i)'. Они одинаковы * для каждого типа *, никаких исключений. Во-вторых, откуда вы знаете, чего хочет OP? Возможно, это именно то, чего хочет OP: переосмыслить каждую пару «short's» как 'int'. И, возможно, 'length' фактически хранит количество' int ', а не количество' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ' – AnT

0

Учитывая определение struct ResampledWavFile

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

и при условии, что объект типа имеет length число short с в resampledSingalData, линии

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; 

вы можете избежать этой проблемы. Однако я не понимаю, как это повлияет на точность ваших численных расчетов.

0

Ответ на вопрос зависит от того, что вам действительно нужно делать. Вы не объяснили это четко, но, похоже, есть несколько возможностей, в зависимости от семантики массива 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 должен быть рей nterpreted как массив int значений (состоящих из двух последовательных трусах каждых) и resWavFile0.length содержит длину этого int массива, то, что вам нужно, это

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

    Но это то же самое, что и исходный вариант, который разбивая , поэтому, по-видимому, эта интерпретация неверна.

Смежные вопросы