向DBus Message追加参数时触发段错误(Segfault)的问题排查求助
问题分析与修复方案
从你的GDB栈追踪和代码来看,段错误的核心原因是调用dbus_message_iter_append_basic时传递的参数格式错误,另外代码里还有几处小问题会导致异常或无输出,下面一步步拆解:
1. 段错误的直接原因:字符串参数传递错误
在libdbus中,dbus_message_iter_append_basic对于DBUS_TYPE_STRING类型,要求传入的是指向字符串的指针的地址(也就是const char**类型)。你直接传递了字符串数组名Parameter,这会导致函数内部错误地把字符串内容当成指针地址来访问,直接触发内存越界和段错误。
看你的代码:
if(!(dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,Parameter)))
正确写法应该传递&Parameter:
if(!(dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &Parameter)))
对比你参考的示例代码,人家也是传的¶m,这一点你没注意到~
2. 其他必须修复的问题
除了段错误,你的代码还有两处会导致异常或无输出的问题:
printf缺少参数:在获取主机名的代码块里,printf("recieved: %s\n");没有传入hio变量,会导致输出乱码或异常,应该改成:printf("recieved: %s\n", hio);Get方法需要两个参数:调用org.freedesktop.DBus.Properties.Get方法时,必须传入两个参数:第一个是接口名(org.freedesktop.hostname1),第二个是属性名(Hostname)。你现在只传了属性名,这会导致DBus服务返回错误,所以需要补充第一个参数:const char* interface = "org.freedesktop.hostname1"; const char* prop_name = "Hostname"; dbus_message_iter_init_append(msg, &iter); // 先追加接口名字符串 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface)) { fprintf(stderr, "Failed to append interface name\n"); exit(1); } // 再追加属性名字符串 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &prop_name)) { fprintf(stderr, "Failed to append property name\n"); exit(1); }
另外,dbus_message_iter_get_basic(&sub, hio)这里也得传&hio,因为函数需要的是指向存储字符串指针的变量的地址,不然也可能触发内存问题。
3. 修复后的核心代码片段
int main(int argc, char*argv[]){ // ... 省略其他初始化代码 ... msg = dbus_message_new_method_call( "org.freedesktop.hostname1", "/org/freedesktop/hostname1", "org.freedesktop.DBus.Properties", "Get" ); if(msg == NULL){ fprintf(stderr, "Error: errDBM--01\n"); exit(1); } dbus_message_iter_init_append(msg, &iter); const char* interface = "org.freedesktop.hostname1"; const char* prop_name = "Hostname"; // 追加第一个参数:接口名 if(!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface)) { fprintf(stderr, "Failed to append interface name\n"); exit(1); } // 追加第二个参数:属性名 if(!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &prop_name)) { fprintf(stderr, "Failed to append property name\n"); exit(1); } // ... 省略发送消息、处理回复的代码 ... if(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING){ char *hio; dbus_message_iter_get_basic(&sub, &hio); printf("recieved: %s\n", hio); } // 别忘了释放消息引用 dbus_message_unref(msg); return 0; }
总结
核心错误就是dbus_message_iter_append_basic的参数传递错误,加上Get方法参数不全、printf缺少参数这几个小问题,修正后应该就能正常运行,获取到主机名了。
内容的提问来源于stack exchange,提问作者MRINAL YADAV
相关产品推荐
相关产品推荐

