2013-03-01 3 views
2

Я получил странное поведение моего кода на C, пока я пытался использовать библиотеку ALSA. Я использовал этот код для генерации SID устройстваСтранное поведение C при использовании alsalib

snd_mixer_selem_id_t* 
getSid(){ 
    snd_mixer_selem_id_t *sid; 
    snd_mixer_selem_id_alloca(&sid); 
    snd_mixer_selem_id_set_index(sid,0); 
    snd_mixer_selem_id_set_name(sid, selem_name); 

    return sid; 
} 

Затем я попытался Acces этой функции

snd_mixer_t *handle = getHandle(); 
snd_mixer_selem_id_t *sid = getSid(); 

snd_mixer_elem_t *elem = snd_mixer_find_selem(handle,sid); 

getHandle() является эквивалент функции, чтобы получить обработчик карты, но это один работают. Странно, что если я использую код функции непосредственно перед использованием функции snd_mixer_find_selem, она работает. Я должен сказать, что я новичок в C, и это один из моих первых проектов, так что это может быть ошибкой новичка с указателями.

Сообщение об ошибке simple.c:282: snd_mixer_selem_get_playback_volume_range: Assertion 'elem' failed.

Так кто-нибудь знает, в чем проблема?

Вот минимальный пример кода, который я использую:

#include <alsa/asoundlib.h> 

static const char *selem_name = "Master"; 
static const char *card = "default"; 

snd_mixer_t* 
getHandle(){ 
    snd_mixer_t *handle; 

    snd_mixer_open(&handle, 0); 
    snd_mixer_attach(handle, card); 
    snd_mixer_selem_register(handle, NULL, NULL); 
    snd_mixer_load(handle); 

    return handle; 
} 

snd_mixer_selem_id_t* 
getSid(){ 
    snd_mixer_selem_id_t *sid; 
    snd_mixer_selem_id_alloca(&sid); 
    snd_mixer_selem_id_set_index(sid,0); 
    snd_mixer_selem_id_set_name(sid, selem_name); 

    return sid; 
} 

void 
incMasterVol(long step){ // Step is a value in [-100,100] 
    long min,max,curr; 

    snd_mixer_t *handle = getHandle(); 

/*snd_mixer_open(&handle, 0); 
    snd_mixer_attach(handle, card); 
    snd_mixer_selem_register(handle, NULL, NULL); 
    snd_mixer_load(handle);*/ 

    snd_mixer_selem_id_t *sid; 
    snd_mixer_selem_id_alloca(&sid); 
    snd_mixer_selem_id_set_index(sid,0); 
    snd_mixer_selem_id_set_name(sid, selem_name); 

    snd_mixer_elem_t *elem = snd_mixer_find_selem(handle,sid); 

    snd_mixer_selem_get_playback_volume_range(elem, &min, &max); 
    snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_SIDE_LEFT, &curr); 
    curr = curr * 100/max; 
    if(curr + step > 100) 
    curr = 100; 
    else if(curr + step < 0) 
    curr = 0; 
    else 
    curr += step; 
    snd_mixer_selem_set_playback_volume_all(elem, curr * max/100); 

    snd_mixer_close(handle); 
} 

void 
toggleMasterVol(){ 
int swiVal; 
snd_mixer_t *handle = getHandle(); 
snd_mixer_elem_t *elem = snd_mixer_find_selem(handle,getSid()); 

snd_mixer_selem_get_playback_switch(elem, SND_MIXER_SCHN_SIDE_LEFT, &swiVal); 
snd_mixer_selem_set_playback_switch_all(elem, !swiVal); 

snd_mixer_close(handle); 
} 

int 
main(int argc, char *argv[]){ 
    incMasterVol(5); 
} 
+0

Нам нужно немного больше контекста исходного кода, чтобы делать полезные предложения. Пожалуйста, разверните свой размещенный исходный код, желательно, чтобы на нем был показан минимальный полнофункциональный пример, демонстрирующий проблему. – datenwolf

+0

Что такое «странное поведение»? Вы никогда не описываете, что происходит, когда оно не «работает». – unwind

+0

При использовании функции getSid я получаю сообщение об ошибке, опубликованное выше. В противном случае он просто работает без ошибок (когда я использую комментарий, а не функцию). – domna

ответ

5

Я думаю, что выводит из alloca() системных вызова

alloca выделить в кадре стеки, поэтому, когда getSid() вернуть ваш выделяются переменным (и когда вы поместили его в основную функцию, он работает, потому что alloca выделяет место на основной записи активации)

Это только предложение, но я думаю, вы должны использовать malloc (то выделить место в куче, поэтому динамическая память выделяется, пока вы не вызовете free() на нем)

попробовать с snd_mixer_selem_id_malloc() вместо :)

+0

Спасибо, это сработало для меня. Но у меня есть еще одна функция под названием «toggleMasterVol()», которая работает с функцией getSid() (я добавил ее к минимальному примеру выше). Вы знаете, почему этот звонок работает? – domna

+0

Указатель dandling - это указатель на недействительный адрес памяти, так что область уже отмечена как свободная диспетчером памяти, но по какой-то причине эта область также может продолжать удерживать ваше старое значение, в этом случае ваша функция получит право структура, но это только удача, если вы добавите некоторый код между вашим 'getSid()' и вашим вызовом toggleMasterVol(), это, возможно, предоставит вам аналоговую ошибку: D – SpectralWave