0

我正在使用 XCode 6 在 Mac OS X 上用 C 语言编写一个库。该库基本上是一个由X-Plane加载的插件,并通过 Web 套接字服务器提供数据。

反过来,该库使用libwebsockets库,该库是我使用开发人员存储库文档中的指南编译的,此处。简而言之,我检查了 libwebsockets 存储库,创建了一个构建目录并运行

cmake ..
make

我的插件 100% 工作,X-Plane 加载它没有任何抱怨......当优化开启时!

当我在 XCode 中禁用对我的库的优化时,将其禁用为None [-O0]时,废话击中了风扇,并且当调用 libwebsockets 函数libwebsocket_create_context()时,库崩溃了。

关闭优化时如何引入错误/崩溃?通常不是相反,打开优化可能会出错吗?

这是围绕故障点的库代码的摘录:

PLUGIN_API int XPluginStart(char *outName, char *outSig, char *outDesc) {
    strcpy(outName, "XP Web Socket");
    strcpy(outSig, "sparkbuzz.plugins.xpwebsocket");
    strcpy(outDesc, "Web socket plugin for streaming data to the browser.");

    struct lws_context_creation_info info;
    info.port = port;
    info.iface = NULL;
    info.protocols = protocols;
    info.extensions = libwebsocket_get_internal_extensions();
    info.ssl_cert_filepath = NULL;
    info.ssl_private_key_filepath = NULL;
    info.gid = -1;
    info.uid = -1;
    info.options = opts;

    context = libwebsocket_create_context(&info); // FAILS HERE WITH EXC_BAD_ACCESS

    if (context == NULL) {
        // libwebsockets initialization has failed!
        return -1;
    }

    // Find XPlane datarefs
    gIAS = XPLMFindDataRef("sim/cockpit2/gauges/indicators/airspeed_kts_pilot");

    // Register flight loop callback
    XPLMRegisterFlightLoopCallback(MyFlightLoopCallback, 1.0, NULL);

    return 1;
}
4

1 回答 1

0

似乎您没有初始化 中的所有字段struct lws_context_creation_info,导致未定义的行为。根据编译器选项和其他难以预测的情况,您的程序实际上可能看起来运行正常……纯属偶然!

您可以通过使用以下命令清除结构来轻松解决此问题memset

struct lws_context_creation_info info;
memset(&info, 0, sizeof info);
info.port = port;
info.iface = NULL;
info.protocols = protocols;
info.extensions = libwebsocket_get_internal_extensions();
info.ssl_cert_filepath = NULL;
info.ssl_private_key_filepath = NULL;
info.gid = -1;
info.uid = -1;
info.options = opts;

在 C99 中执行此操作的另一种方法是这样初始化结构:

struct lws_context_creation_info info = {
    .port = port,
    .iface = NULL,
    .protocols = protocols,
    .extensions = libwebsocket_get_internal_extensions(),
    .ssl_cert_filepath = NULL,
    .ssl_private_key_filepath = NULL,
    .gid = -1,
    .uid = -1,
    .options = opts };

任何其他字段都将被初始化为00.0NULL取决于类型,因此您可以省略ifacessl_cert_filepath和的初始化程序ssl_private_key_filepath

重要的是始终使用通用方法来初始化具有自动存储的结构,以防止在以后使用新字段扩展结构时或在您忘记某些初始化器的地方时出现虚假的难以发现的错误。

另请注意,此函数的前 3 行也有风险:

strcpy(outName, "XP Web Socket");
strcpy(outSig, "sparkbuzz.plugins.xpwebsocket");
strcpy(outDesc, "Web socket plugin for streaming data to the browser.");

输出字符数组的大小未知。可能会发生缓冲区溢出。将缓冲区大小作为参数传递或将它们指定为常量并检查内容是否适合。

于 2015-02-27T00:05:40.353 回答