2010-12-28 6 views
0

내가 정의 TCL 인터프리터를 가지고와 "자유() 잘못된 포인터를". 여기있다 : 나는 다음과 같은 명령을 main.cpp를 구축방법 : 사용자 지정 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; 
} 

:

g++ -DNDEBUG -O3 -fpic -Wall -pedantic -fno-strict-aliasing \ 
    -Wl,-R/usr/local/lib -L/usr/local/lib -ltcl main.cpp -o myinterp 

때때로 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] 

main.cpp에 문제가 있습니까? 이 충돌을 일으키는 원인은 무엇일까요? AddressOf를 & 조작없이

Tcl_Main(argc, argv, Tcl_AppInit); 

:

+4

Valgrind의 시간 : –

답변

0

나는 Tcl_Main이처럼해야한다고 생각합니다. 예를 들어 here을 참조하십시오. 인수의 자동 처리를 우회하기 위해 argv의 크기에 대해 Tcl_Main에 연결하고 있습니까?

편집 : 어떻게 그 가치를 위해, 나는이 코드를 분명히 잘못,하지만 내 의견이 훨씬 가치가 없을 수도 사업자의 주소를 통해 내 정신 수차를 주어 아무것도 표시되지 않습니다. 스크립트를 아무 문제없이 표준 tclsh 인터프리터로 사용할 수 있습니까? 다른 확장 프로그램이나 라이브러리를로드합니까?

+3

'Tcl_AppInit'와'& Tcl_AppInit'은 동일합니다. –

+0

Doh - 물론 그렇습니다. 실제로이 기능을 호출하기보다는 주소를 가져다가 사용한다는 것을 보여주는 것은 물론 더 정확합니다. – Jackson

+0

@Jackson 예'argv'의 크기에 관해 필적하고 있습니다. 이 커스텀 TCL 인터프리터를 작성하는 목적은'myinterp some.tcl'이'some.tcl'을 처리하고 대화 형 TCL 세션이 존재하지 않는 상황을 만드는 것입니다. 당신이 이것을 성취 할 수있는 더 좋은 방법을 제안 할 수 있다면, 나는 감사 할 것입니다. – Vahagn

2

이 같은 코드를 작성 나을 수 있습니다 : 그런

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

std::string의 버퍼의 수명을 내 직관이 나타내는 것 인, 올바른 것입니다 아마 당신의 진짜 문제. (일단 손상된 메모리가 있으면 충돌은 거의 어디에서나 발생할 수 있습니다.) 그러나 파일 이름에 공백이 있으면 여전히 철저히 잘못 될 것입니다. 어쩌면 괜찮을 것입니다. (예를 들어, "nice"이름을 가진 모든 로컬 파일 이름 일 경우) Tcl의 Tcl_EvalObjv을 사용하면 다음과 같이 실행됩니다. (조금 더 길어 C++가 아니라 실제로 C입니다.)

int 
Tcl_AppInit(Tcl_Interp* interp) 
{ 
    Tcl_Obj *script[2]; 
    int code = TCL_OK; 

    if (Tcl_Init(interp) == TCL_ERROR) { 
     return TCL_ERROR; 
    } 
    script[0] = Tcl_NewStringObj("source", -1); 
    Tcl_IncrRefCount(script[0]); 
    for (int i = 1; i < argc && code == TCL_OK; ++i) { 
     script[1] = Tcl_NewStringObj(argv[i], -1); 
     Tcl_IncrRefCount(script[1]); 
     if (Tcl_EvalObjv(interp, 2, script, 0/*no special flags*/) != TCL_OK) { 
      code = TCL_ERROR; 
     } 
     Tcl_DecrRefCount(script[1]); 
    } 
    Tcl_DecrRefCount(script[0]); 
    return code; 
} 
+0

"좋은"파일 이름의 경우를 고려하십시오. 나는'Tcl_Eval (interp, ("source"+ std :: string (argv [i])) .c_str())'호출에 문제가 있다고 생각하지 않는다. 'c_str()'을 호출하는 임시'std :: string' 객체는 바로 생성 된 블록의 끝까지 존재합니까?따라서'for' 루프에서 각 반복문이 끝날 때 파괴되고 있으므로'Tcl_Eval' 실행 중에 임시 객체가 여전히 존재합니다. 내가 잘못? – Vahagn

+0

@Vahagn : 사용에 대해 매우주의를 기울여야한다는 가정이 있습니다. 게다가'Tcl_VarEval'을 사용하여 Tcl에 연결을시킬 수 있습니다. –

관련 문제