【问题标题】:Strange C behaviour when using alsalib使用 alsalib 时出现奇怪的 C 行为
【发布时间】:2013-02-15 23:20:12
【问题描述】:

当我尝试使用 ALSA 库时,我的 C 代码出现了一个奇怪的行为。 我使用此代码生成设备的 sid

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;
}

然后我尝试通过

访问此功能
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);
}

【问题讨论】:

  • 我们需要更多的源代码上下文来提出有用的建议。请扩展您发布的源代码,最好是展示问题的最小完整功能示例。
  • 什么是“奇怪的行为”?你永远不会描述当它不“工作”时会发生什么。
  • 使用getSid 函数时,我收到上面发布的错误消息。否则它只会正常工作而不会出现任何错误(当我使用注释块而不是函数时)。

标签: c alsa


【解决方案1】:

在遇到同样的问题并稍作搜索后,我有一个提示给你:更改selem_name 的值,如有必要,更改card 的值!通过发出以下系统命令找出正确的卡名:

cat /proc/asound/cards

然后,使用alsamixer 确定所需音量控制的名称。就我而言,这是Digital,但请自己尝试一下。

【讨论】:

    【解决方案2】:

    我认为这源自alloca() 系统调用

    alloca 在堆栈帧中分配,因此当getSid() 返回时,您分配的变量被释放,最终得到一个摇晃的指针...(当您将它放在主函数中时,它可以工作,因为alloca在主激活记录上分配空间)

    这只是一个建议,但我认为您应该使用malloc(在堆上分配空间,因此在您调用free()之前分配动态内存)

    改用snd_mixer_selem_id_malloc() :)

    【讨论】:

    • 谢谢,这对我有用。但是我有另一个函数叫做toggleMasterVol(),它与getSid() 函数一起工作(我将它添加到上面的最小示例中)。你可能知道为什么这个调用有效吗?
    • 悬空指针是指向无效内存地址的指针,因此该区域已被内存管理器标记为空闲,但由于某种原因,该区域也可以继续保存您的旧值,在在这种情况下,您的函数会获得正确的结构,但这只是运气,如果您在 getSid()toggleMasterVol() 调用之间添加一些代码,它可能会给您带来模拟错误:D
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-02
    • 1970-01-01
    • 2018-05-26
    相关资源
    最近更新 更多