C++ 获得;free():无效指针";使用定制的TCL解释器

C++ 获得;free():无效指针";使用定制的TCL解释器,c++,malloc,free,tcl,glibc,C++,Malloc,Free,Tcl,Glibc,我有一个定制的TCL解释器。这是: // file main.cpp #include <tcl.h> #include <string> int argc = 0; char** argv = 0; int Tcl_AppInit( Tcl_Interp* interp ) { if ( Tcl_Init( interp ) == TCL_ERROR ) { return TCL_ERROR; } for ( in

我有一个定制的TCL解释器。这是:

// file main.cpp
#include <tcl.h>
#include <string>

int    argc = 0;
char** argv = 0;

int
Tcl_AppInit( Tcl_Interp* interp ) 
{
    if ( Tcl_Init( interp ) == TCL_ERROR ) {
        return TCL_ERROR;  
    }
    for ( int i = 1; i < argc; ++i ) {             
        if ( Tcl_Eval( interp, ("source " + std::string( argv[i] )).c_str() ) == TCL_ERROR ) {
            return TCL_ERROR;
        }
    }
    return TCL_OK;
}

int
main( int argc, char** argv )
{
    ::argc = argc;
    ::argv = argv;
    Tcl_Main( 1, argv, &Tcl_AppInit );
    return 0;
}
有时
myinterp
会出现如下错误消息:

free(): invalid pointer: 0x00002b04078aa000 ***
======= Backtrace: =========
/lib64/libc.so.6[0x3723c722ef]
/lib64/libc.so.6(cfree+0x4b)[0x3723c7273b]
/lib64/libc.so.6(_IO_free_backup_area+0x18)[0x3723c6e1d8]
/lib64/libc.so.6(_IO_file_overflow+0x1d2)[0x3723c6c1d2]
/lib64/libc.so.6(_IO_file_xsputn+0xf2)[0x3723c6ce22]
/lib64/libc.so.6(_IO_vfprintf+0x1b0)[0x3723c428a0]
/lib64/libc.so.6(_IO_fprintf+0x88)[0x3723c4d358]
Tcl_Main(argc, argv, Tcl_AppInit);
int
Tcl_AppInit( Tcl_Interp* interp )
{
    if ( Tcl_Init( interp ) == TCL_ERROR ) {
        return TCL_ERROR;
    }
    for ( int i = 1; i < argc; ++i ) {
        std::string script("source ");

        script += argv[i];
        if ( Tcl_Eval( interp, script.c_str() ) == TCL_ERROR ) {
            return TCL_ERROR;
        }
    }
    return TCL_OK;
}

main.cpp
有问题吗?是什么导致了这次崩溃?

我认为Tcl\u Main应该是这样的:

free(): invalid pointer: 0x00002b04078aa000 ***
======= Backtrace: =========
/lib64/libc.so.6[0x3723c722ef]
/lib64/libc.so.6(cfree+0x4b)[0x3723c7273b]
/lib64/libc.so.6(_IO_free_backup_area+0x18)[0x3723c6e1d8]
/lib64/libc.so.6(_IO_file_overflow+0x1d2)[0x3723c6c1d2]
/lib64/libc.so.6(_IO_file_xsputn+0xf2)[0x3723c6ce22]
/lib64/libc.so.6(_IO_vfprintf+0x1b0)[0x3723c428a0]
/lib64/libc.so.6(_IO_fprintf+0x88)[0x3723c4d358]
Tcl_Main(argc, argv, Tcl_AppInit);
int
Tcl_AppInit( Tcl_Interp* interp )
{
    if ( Tcl_Init( interp ) == TCL_ERROR ) {
        return TCL_ERROR;
    }
    for ( int i = 1; i < argc; ++i ) {
        std::string script("source ");

        script += argv[i];
        if ( Tcl_Eval( interp, script.c_str() ) == TCL_ERROR ) {
            return TCL_ERROR;
        }
    }
    return TCL_OK;
}
没有操作员的地址(&O)。请参见这里的示例。我想你是在向Tcl_Main谎报argv的大小,以绕过参数的自动处理


编辑:不管它值多少钱,我看不出代码有任何明显的错误,但考虑到我在操作员地址上的精神失常,我的意见可能没有多大价值。您能否将脚本源代码转换成标准的tclsh解释器而不出现任何问题?他们是否加载了其他扩展或库?

您最好这样编写代码:

free(): invalid pointer: 0x00002b04078aa000 ***
======= Backtrace: =========
/lib64/libc.so.6[0x3723c722ef]
/lib64/libc.so.6(cfree+0x4b)[0x3723c7273b]
/lib64/libc.so.6(_IO_free_backup_area+0x18)[0x3723c6e1d8]
/lib64/libc.so.6(_IO_file_overflow+0x1d2)[0x3723c6c1d2]
/lib64/libc.so.6(_IO_file_xsputn+0xf2)[0x3723c6ce22]
/lib64/libc.so.6(_IO_vfprintf+0x1b0)[0x3723c428a0]
/lib64/libc.so.6(_IO_fprintf+0x88)[0x3723c4d358]
Tcl_Main(argc, argv, Tcl_AppInit);
int
Tcl_AppInit( Tcl_Interp* interp )
{
    if ( Tcl_Init( interp ) == TCL_ERROR ) {
        return TCL_ERROR;
    }
    for ( int i = 1; i < argc; ++i ) {
        std::string script("source ");

        script += argv[i];
        if ( Tcl_Eval( interp, script.c_str() ) == TCL_ERROR ) {
            return TCL_ERROR;
        }
    }
    return TCL_OK;
}

Tcl\u-AppInit
&Tcl\u-AppInit
是相同的。Doh-是的,当然是这样,而且更正确,因为它表明您真的想获取地址而不是调用函数。@Jackson是的,我在撒谎
argv
的大小。编写此自定义TCL解释器的目的是使
myinterp some.TCL
处理
some.TCL
而不存在交互式TCL会话。如果您能提出另一种更好的方法来实现这一点,我将不胜感激。@Vahagn:有一些代码(在注释中;单击以显示)在纯Tcl中实现了命令循环(即REPL)。只要有一个包含该代码的脚本,您就能够与Tcl解释器进行交互,尽管从文件加载代码。或者你可以使用Tclx软件包中更精致的东西。@Donal Fellows我使用的是Tclx软件包,但它会导致Tk出现一些问题。在<代码>命令循环- < /COD>交互>所有GUI挂起,如果您不永久调用TEH<代码> Update < /Cord>命令。请考虑“尼斯”文件名的情况。我认为call
Tcl_Eval(interp,(“source”+std::string(argv[I])).c_str()没有问题。
。我为其调用
c_str()
的临时
std::string
对象一直存在,直到创建它的块结束,对吗?因此,它将在每次迭代结束时在
for
循环中被销毁,因此在执行
Tcl\u Eval
期间,临时对象仍然存在。“我错了吗?”瓦哈根:这是一种假设,我会非常谨慎地使用它。另外,您还可以使用
Tcl\u VarEval
让Tcl为您进行连接。