Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
导致分段错误的TCL\u链接\u字符串(堆芯转储)_C_Multithreading_Tcl - Fatal编程技术网

导致分段错误的TCL\u链接\u字符串(堆芯转储)

导致分段错误的TCL\u链接\u字符串(堆芯转储),c,multithreading,tcl,C,Multithreading,Tcl,我试图与c和tcl共享一个变量,问题是当我试图从tcl读取c线程中的变量时,它会导致分段错误,我不确定这是正确的方法,但它似乎适用于ints。导致分段错误的部分是这一行,当我试图打印“Var”时,但我想读取变量,以便在变量更改时执行相应的操作 这是我正在使用的C代码 void mode_service(ClientData clientData) { while(1) { char* Var = (char *) clientData; printf("%s\n", Var);

我试图与c和tcl共享一个变量,问题是当我试图从tcl读取c线程中的变量时,它会导致分段错误,我不确定这是正确的方法,但它似乎适用于ints。导致分段错误的部分是这一行,当我试图打印“Var”时,但我想读取变量,以便在变量更改时执行相应的操作

这是我正在使用的C代码

void mode_service(ClientData clientData) {

while(1) {
    char* Var = (char *) clientData;
    printf("%s\n", Var);

    usleep(100000); //100ms
 }
}


static int mode_thread(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
Tcl_ThreadId id;    
ClientData limitData;

limitData = cdata;
id = 0;
Tcl_CreateThread(&id, mode_service, limitData, TCL_THREAD_STACK_DEFAULT, TCL_THREAD_NOFLAGS);
printf("Tcl_CreateThread id = %d\n", (int) id);

// Wait thread process, before returning to TCL prog
int i, aa;
for (i=0 ; i<100000; i++) {aa = i;}

// Return thread ID to tcl prog to allow mutex use
Tcl_SetObjResult(interp, Tcl_NewIntObj((int)id));
printf("returning\n");
return TCL_OK;  
}


int DLLEXPORT Modemanager_Init(Tcl_Interp *interp){
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
    return TCL_ERROR;
}
if (Tcl_PkgProvide(interp, "PCIe", "1.0") == TCL_ERROR) {
    return TCL_ERROR;
}

// Create global Var
int *sharedPtr=NULL;
//sharedPtr = sharedPtr = (char *) Tcl_Alloc(sizeof(char));
Tcl_LinkVar(interp, "mode", (char *) &sharedPtr, TCL_LINK_STRING);


Tcl_CreateObjCommand(interp, "mode_thread", mode_thread, sharedPtr, NULL);
return TCL_OK;
}

你的代码乱七八糟!你需要决定你在做什么,然后就这么做。特别是,您使用的是
Tcl_LinkVar
,因此您需要决定链接到哪种类型的变量。如果存储、C访问模式和声明的语义类型之间不匹配,就会导致崩溃

因为您的代码太复杂了,我无法准确地理解您想要做什么,所以我将用不太密切相关的示例进行说明。您需要从他们那里了解如何更改代码中的内容以获得所需的结果

链接整数变量 让我们做一个简单的例子:一个全局
int
变量(在任何函数之外声明)

您希望您的C代码读取该变量并获取值。容易的!只要在范围内阅读即可。您还希望Tcl代码能够写入该变量。容易的!在package initialization函数中,输入以下内容:

Tcl_LinkVar(interp              /* == the Tcl interpreter context */,
            "sharedVal"         /* == the Tcl name */,
            (char *) &sharedVal /* == pointer to C variable */,
            TCL_LINK_INT        /* == what is it! An integer */);
请注意,在此之后(直到您
Tcl\u UnlinkVar
),每当Tcl代码从Tcl变量读取时,当前值将从C变量中获取并转换

如果希望该变量位于堆上,请执行以下操作:

int *sharedValPtr = malloc(sizeof(int));
C代码使用
*sharedValPtr
访问,您可以通过以下方式绑定到Tcl:

Tcl_LinkVar(interp                /* == the Tcl interpreter context */,
            "sharedVal"           /* == the Tcl name */,
            (char *) sharedValPtr /* == pointer to C variable */,
            TCL_LINK_INT          /* == what is it! An integer */);
链接字符串变量 还有一系列其他语义类型,还有
TCL\u LINK INT
(请参阅列表的文档),但它们都遵循这种模式,但除了
TCL\u LINK\u STRING
。有了这些,你就可以:

char *sharedStr = NULL;
您还需要注意的是,字符串将始终使用
Tcl_Alloc
(对于典型的Tcl内存使用模式,它比大多数系统内存分配器快得多)分配,而不使用任何其他内存分配器,因此也将始终使用
Tcl_Free
解除分配。实际上,这意味着如果从C端设置字符串,则必须使用
Tcl\u Alloc
来分配内存

发布更新通知
最后一点需要注意的是,当您从C端设置变量,但希望Tcl注意到已经设置了更改(例如,因为设置了
trace
,或者因为您已经在Tk GUI中显示了值),您应该执行
Tcl\u updatelinkdvar
,让Tcl知道发生了一个它应该注意的更改。如果您从未使用跟踪(或Tk GUI,或
vwait
命令)监视变量的更新,则可以忽略此API调用。

Donal的回答是正确的,但我尝试向您展示您对ClientData所做的操作

澄清一下:采用函数指针的所有(或几乎所有Idk)Tcl函数也采用
ClientData
类型的参数,该参数在Tcl调用函数时传递给函数

让我们看看这一行:

Tcl_CreateObjCommand(interp, "mode_thread", mode_thread, NULL, NULL);
// ------------------------------------------------------^^^^
您总是将
NULL
作为
ClientData
传递给
mode\u线程
函数。
mode\u-thread
函数中,使用传递的
ClientData
NULL
)将其作为ClientData传递给新线程:

limitData = cdata;
// ...
Tcl_CreateThread(&id, mode_service, limitData, TCL_THREAD_STACK_DEFAULT, TCL_THREAD_NOFLAGS);
mode\u service
功能中,您使用
ClientData
(仍然为
NULL
)作为指向
char
数组的指针:

char* Var = (char *) clientData;
它是指向地址的指针
0x00

然后告诉
printf
取消对该空指针的引用:

printf("%s\n", Var);

这显然会使您的程序崩溃。

如何定义
ClientData
?@BitFiddlingCodeMonkey它是
typedef
用于
void*
(可以追溯到
void*
之前,在编译器中很常见!)并且通常传达了一个承诺,Tcl不会看指针,而是只发送它。我临时将这个问题重命名为“
printf(“%s”,NULL)
崩溃我的程序”我对Tcl的混合编程相当陌生,因此,我应该在调用Tcl_CreateObjCommand时传递一个ClientData变量,以便能够在mode_服务中读取变量的addr。?ClientData可以是任何您喜欢的。Tcl刚刚经过。你想怎么做就怎么做,否则你可以忽略它。这取决于您(如果您需要ClientData,您会很高兴它在那里,而不是相反),我唯一想做的就是从C中的mode_服务函数中读取tcl变量“mode”,一旦我能够在变量发生变化时立即读取它,我将根据“mode”的值执行相应的指令。很抱歉,如果代码一团糟,我对tcl/c编程还相当陌生,这只是一个概念证明
limitData = cdata;
// ...
Tcl_CreateThread(&id, mode_service, limitData, TCL_THREAD_STACK_DEFAULT, TCL_THREAD_NOFLAGS);
char* Var = (char *) clientData;
printf("%s\n", Var);