Problem with Tcl_Alloc, Tcl_LinkVar, and segmentation faults 
Author Message
 Problem with Tcl_Alloc, Tcl_LinkVar, and segmentation faults

I am trying to built an application that uses a Tk GUI front end to a
C program. I need to create some method of getting data back and
forth, and have hit a snag. It seems there are (at least) two
different approaches I can take. The first is to use Tcl_SetVar every
time I want to update a variable, and Tcl_GetVar to read them. This
seems to work, but would spread Tcl calls throughout the C code.

An alternate approach would seem to be to use Tcl_LinkVar to for a
link between some C variable, and a corresponding Tcl variable, and
then the content is always updated (according to the man pages at
least). When using string variables (from the C side) it also seems
that you must use Tcl_Alloc to allocate the space for a variable (on
the Tcl side), and then use Tcl_LinkVar to make the link.

When I do this I always get a segmentation crash when I try to update
the variable on the C side. Here is the C code, and the Tcl script is
a simple Tk script that does a "puts Background".

#include <tk.h>

int Tk_AppInit(Tcl_Interp *interp);

char   *bg_ptr, background;

/*****    Define Function Header   *****/

void main(void)
{
  int   myargc;
  char  *myargv[2];

  myargc = 2;                 /* Number of arguments expected by
Tk_Main   */
  myargv[0] = "trash";        /* Prgram name (not used)
*/
  myargv[1] = "test.tcl";     /* Tcl/Tk script to run
*/

  Tk_Main(myargc, myargv, Tk_AppInit);

Quote:
}

int
Tk_AppInit(Tcl_Interp *interp) {

  int resp;

  /*
   * Initialize packages
   */
  if (Tcl_Init(interp) == TCL_ERROR) {
          return TCL_ERROR;
  }
  if (Tk_Init(interp) == TCL_ERROR) {
          return TCL_ERROR;
  }

  /*
   * Define start-up filename. This file is read in
   * case the program is run interactively.
   */
  Tcl_SetVar(interp, "tcl_rcFileName", "~./exlog",
          TCL_GLOBAL_ONLY);

  bg_ptr = Tcl_Alloc(10);
  bg_ptr = &background;
  resp = Tcl_LinkVar(interp, "Background", bg_ptr,
        TCL_LINK_STRING | TCL_LINK_READ_ONLY);
  if (resp != TCL_OK) {
    fprintf(stderr, "TCL Error: %s \n", interp->result);
    exit();
  }
  fprintf(stderr, "Now do copy....\n");
  fflush(stderr);
  strcpy(bg_ptr,"blue");

/****
******/

/****
  bg_ptr = &background;
  strcpy(bg_ptr,"pink");
  Tcl_SetVar(interp, "Background", bg_ptr,
        TCL_GLOBAL_ONLY);
******/

  return TCL_OK;

Quote:
}

Any help greatly appreciated.

BTW, I have seen no information on the relative efficiency of these
different approaches. Is there any large differences?

Thanks.

Al



Sun, 13 Oct 2002 03:00:00 GMT  
 Problem with Tcl_Alloc, Tcl_LinkVar, and segmentation faults

Quote:

> I am trying to built an application that uses a Tk GUI front end to a
> C program. I need to create some method of getting data back and
> forth, and have hit a snag. It seems there are (at least) two
> different approaches I can take. The first is to use Tcl_SetVar every
> time I want to update a variable, and Tcl_GetVar to read them. This
> seems to work, but would spread Tcl calls throughout the C code.

The best way to do this is to provide Tcl commands which allow access to your
C code.

Quote:
> An alternate approach would seem to be to use Tcl_LinkVar to for a
> link between some C variable, and a corresponding Tcl variable, and
> then the content is always updated (according to the man pages at
> least). When using string variables (from the C side) it also seems
> that you must use Tcl_Alloc to allocate the space for a variable (on
> the Tcl side), and then use Tcl_LinkVar to make the link.

This still requires that you add a call to Tcl_UpdateLinkedVar whenever you
change the C variable.

Quote:
> When I do this I always get a segmentation crash when I try to update
> the variable on the C side. Here is the C code, and the Tcl script is
> a simple Tk script that does a "puts Background".

> #include <tk.h>

> int Tk_AppInit(Tcl_Interp *interp);

> char   *bg_ptr, background;

> /*****    Define Function Header   *****/

> void main(void)
> {
>   int   myargc;
>   char  *myargv[2];

>   myargc = 2;                 /* Number of arguments expected by
> Tk_Main   */
>   myargv[0] = "trash";        /* Prgram name (not used)
> */
>   myargv[1] = "test.tcl";     /* Tcl/Tk script to run
> */

>   Tk_Main(myargc, myargv, Tk_AppInit);

> }

> int
> Tk_AppInit(Tcl_Interp *interp) {

>   int resp;

>   /*
>    * Initialize packages
>    */
>   if (Tcl_Init(interp) == TCL_ERROR) {
>           return TCL_ERROR;
>   }
>   if (Tk_Init(interp) == TCL_ERROR) {
>           return TCL_ERROR;
>   }

>   /*
>    * Define start-up filename. This file is read in
>    * case the program is run interactively.
>    */
>   Tcl_SetVar(interp, "tcl_rcFileName", "~./exlog",
>           TCL_GLOBAL_ONLY);

>   bg_ptr = Tcl_Alloc(10);
>   bg_ptr = &background;

The above line is completely wrong as it causes you to throw away what you
have allocated and replace it with a pointer to something which was not
allocated.

Quote:
>   resp = Tcl_LinkVar(interp, "Background", bg_ptr,

If you read the Tcl_LinkVar documentation you will notice that you have to
pass the address of the variable, not the value of the variable as you have
done. So replace bg_ptr with &bg_ptr.

Quote:
>         TCL_LINK_STRING | TCL_LINK_READ_ONLY);
>   if (resp != TCL_OK) {
>     fprintf(stderr, "TCL Error: %s \n", interp->result);
>     exit();
>   }
>   fprintf(stderr, "Now do copy....\n");
>   fflush(stderr);
>   strcpy(bg_ptr,"blue");

When you change the variable you must call Tcl_UpdateLinkedVar, otherwise
Tcl does not know that you have changed it.

- Show quoted text -

Quote:

> /****
> ******/

> /****
>   bg_ptr = &background;
>   strcpy(bg_ptr,"pink");
>   Tcl_SetVar(interp, "Background", bg_ptr,
>         TCL_GLOBAL_ONLY);
> ******/

>   return TCL_OK;
> }

> Any help greatly appreciated.

> BTW, I have seen no information on the relative efficiency of these
> different approaches. Is there any large differences?

No, neither from performance or amount of code you have to add to your C
code to make it work.


Tue, 15 Oct 2002 03:00:00 GMT  
 Problem with Tcl_Alloc, Tcl_LinkVar, and segmentation faults
Thanks for the suggestions. I did change the call to Tcl_LinkVar and
now the strings work correctly. (Other variable types always did work
correctly.)

Sorry about the confusing code sample. It was a mixed bag of trying to
use Tcl_SetVar and the Tcl_LinkVar approaches, and the memory
allocation part was incorrect.

As for Tcl_UpdateVar, I do not seem to have to do this. When I change
the variable on the C side, it shows up just fine on the tcl side.
This is the way it is documented (as of 8.3.0 at least), and the only
time you would need the Tcl_UpdateVar would be if you were doing
variable tracing or debugging on the tcl side AFAIK.

I also thought of trying to set up a C procedure call from tcl. In
order to learn something about this (being very new to all this), I
tried the example from the Practical Programming book. It would not
work for me. It would not even configure the basic examples from the
book, and it seemed overly complicated. I have a very short schedule
to get something working, so I gave up on that approach. Someday I
might have the time to understand all the stuff involved (with
configure, and magic makefiles, etc.) but for now I just manually did
my makefiles and took the LinkVar approach. (I did send an email
question off to Brent Welsh, but he misunderstood the problem at
first, and I ran out of time to pursue it with him. Someday I hope to
revisit this.)

Thanks again for the help.

Al



Tue, 15 Oct 2002 03:00:00 GMT  
 
 [ 3 post ] 

 Relevant Pages 

1. segmentation fault in t_splay() calling Tcl_Alloc()

2. Another Segmentation Fault problem

3. Strange segmentation fault problem with C++ extension

4. how to find segmentation fault problem with Sun f90

5. Memory problem Segmentation fault / exhaust

6. segmentation fault problem

7. dimensions and segmentation fault problem

8. Segmentation Fault problem

9. Seg fault with Tcl_LinkVar

10. visual works 3.1 image has segmentation fault on 2.4 kernel (red hat 8.0)

11. segmentation fault on gabage collect

12. Segmentation faults

 

 
Powered by phpBB® Forum Software