1. what am I missing?

here C code from termbits.h

typedef unsigned char cc_t;
typedef unsigned int speed_t;
typedef unsigned int tcflag_t;

  1. define NCCS 19 /* there should be a sharp character before define not 1. */

    struct termios2 {
    tcflag_t c_iflag; /* input mode flags */
    tcflag_t c_oflag; /* output mode flags */
    tcflag_t c_cflag; /* control mode flags */
    tcflag_t c_lflag; /* local mode flags */
    cc_t c_line; /* line discipline */
    cc_t c_cc[NCCS]; /* control characters */
    speed_t c_ispeed; /* input speed */
    speed_t c_ospeed; /* output speed */
    };

    from this I compute 44 bytes for termios2 struct:
    4*4 + 1 + 19 + 2*4 = 44
    But if I allocate 44 bytes my program crash.
    I must allocate 45 bytes for it to works. Where is the missing byte?

    Jacques
new topic     » topic index » view message » categorize

2. Re: what am I missing?

jacques_desch said...

here C code from termbits.h

typedef unsigned char	cc_t; 
typedef unsigned int	speed_t; 
typedef unsigned int	tcflag_t; 
 
#define NCCS 19 
 
struct termios2 { 
	tcflag_t c_iflag;		/* input mode flags */ 
	tcflag_t c_oflag;		/* output mode flags */ 
	tcflag_t c_cflag;		/* control mode flags */ 
	tcflag_t c_lflag;		/* local mode flags */ 
	cc_t c_line;			/* line discipline */ 
	cc_t c_cc[NCCS];		/* control characters */ 
	speed_t c_ispeed;		/* input speed */ 
	speed_t c_ospeed;		/* output speed */ 
}; 

from this I compute 44 bytes for termios2 struct:

4*4 + 1 + 19 + 2*4 = 44

But if I allocate 44 bytes my program crash. I must allocate 45 bytes for it to works. Where is the missing byte?

Jacques

The C language leaves the packaging of data within a struct up to the compiler. Most compliers add padding bytes in order to ensure alignment of data on certain boundaries. In this case, it would appear that it tries to make sure that each new field begins on an even address, so I'm guessing there is a hidden padding byte between c_line and c_cc fields. However, that would also mean that you need to allocate 46 bytes because there should also be a padding byte after c_cc field.

By the way, in this forum you can use {{{ }}} to set aside a block of text that is not inspected for markup tags such as '#'.

new topic     » goto parent     » topic index » view message » categorize

3. Re: what am I missing?

DerekParnell said...
jacques_desch said...

here C code from termbits.h

typedef unsigned char	cc_t; 
typedef unsigned int	speed_t; 
typedef unsigned int	tcflag_t; 
 
#define NCCS 19 
 
struct termios2 { 
	tcflag_t c_iflag;		/* input mode flags */ 
	tcflag_t c_oflag;		/* output mode flags */ 
	tcflag_t c_cflag;		/* control mode flags */ 
	tcflag_t c_lflag;		/* local mode flags */ 
	cc_t c_line;			/* line discipline */ 
	cc_t c_cc[NCCS];		/* control characters */ 
	speed_t c_ispeed;		/* input speed */ 
	speed_t c_ospeed;		/* output speed */ 
}; 

from this I compute 44 bytes for termios2 struct:

4*4 + 1 + 19 + 2*4 = 44

But if I allocate 44 bytes my program crash. I must allocate 45 bytes for it to works. Where is the missing byte?

Jacques

The C language leaves the packaging of data within a struct up to the compiler. Most compliers add padding bytes in order to ensure alignment of data on certain boundaries. In this case, it would appear that it tries to make sure that each new field begins on an even address, so I'm guessing there is a hidden padding byte between c_line and c_cc fields. However, that would also mean that you need to allocate 46 bytes because there should also be a padding byte after c_cc field.

Yes, it's very compiler dependent. I added the following to your struct definition:

#include <stdio.h> 
 
int main(){ 
	struct termios2 t; 
	printf("termios2: %d\n", sizeof( struct termios2 ) ); 
	printf("c_iflag:  %p\n", &t.c_iflag ); 
	printf("c_oflag:  %p\n", &t.c_oflag ); 
	printf("c_cflag:  %p\n", &t.c_cflag ); 
	printf("c_lflag:  %p\n", &t.c_lflag ); 
	printf("c_line:   %p\n", &t.c_line ); 
	printf("c_cc:     %p\n", &t.c_cc ); 
	printf("c_ispeed: %p\n", &t.c_ispeed ); 
	printf("c_ospeed: %p\n", &t.c_ospeed ); 
	return 0; 
} 
And with OpenWatcom v1.8, here's what I got:
  termios2: 44 
  c_iflag:  0006fe68 
  c_oflag:  0006fe6c 
  c_cflag:  0006fe70 
  c_lflag:  0006fe74 
  c_line:   0006fe78 
  c_cc:     0006fe79 
  c_ispeed: 0006fe8c 
  c_ospeed: 0006fe90 
So OW1.8 at least doesn't pad between byte sized members.

Matt

new topic     » goto parent     » topic index » view message » categorize

4. Re: what am I missing?

You guys shouldn't be counting bytes. Use the sizeof() operator the C compiler will tell you how big the structure is.

new topic     » goto parent     » topic index » view message » categorize

5. Re: what am I missing?

SDPringle said...

You guys shouldn't be counting bytes. Use the sizeof() operator the C compiler will tell you how big the structure is.

I'm not writing C code but euphoria binding to termios, so sizeof() is of no use to me. Anyway there is not padding as when I peek the struct all members are at expected position here the code:

function peek_termios(atom pTermios) 
  return peek4u({pTermios,4}) & peek(pTermios+16) &  
         {peek({pTermios+17,NCCS})} & peek4u({pTermios+17+NCCS,2}) 
end function 
 
 

the extra byte is at end of allocated struct. Matt code give this on Linpus lite compiled with gcc 4.1.2

termios2: 44 
c_iflag:  0xbfc9e408 
c_oflag:  0xbfc9e40c 
c_cflag:  0xbfc9e410 
c_lflag:  0xbfc9e414 
c_line:   0xbfc9e418 
c_cc:     0xbfc9e419 
c_ispeed: 0xbfc9e42c 
c_ospeed: 0xbfc9e430 
So there is no padding between fields but allocationg 44 crash my program. Well I will take it as a mystery and go on with TERMIOS_SIZE=45

jacques

new topic     » goto parent     » topic index » view message » categorize

6. Re: what am I missing?

jacques_desch said...

the extra byte is at end of allocated struct. Matt code give this on Linpus lite compiled with gcc 4.1.2

termios2: 44 
c_iflag:  0xbfc9e408 
c_oflag:  0xbfc9e40c 
c_cflag:  0xbfc9e410 
c_lflag:  0xbfc9e414 
c_line:   0xbfc9e418 
c_cc:     0xbfc9e419 
c_ispeed: 0xbfc9e42c 
c_ospeed: 0xbfc9e430 
So there is no padding between fields but allocationg 44 crash my program. Well I will take it as a mystery and go on with TERMIOS_SIZE=45

That's odd. What happens if you do the same in C? Meaning, can you malloc 44 bytes and not have it crash?

It sounds like the code is writing out of bounds somewhere. Actually, I'd recommend running it under valgrind, so see where the illegal access is happening. Sounds like a bug in the library. If you do any C coding on Linux, valgrind can be your best friend for tracking down weird memory issues.

Matt

new topic     » goto parent     » topic index » view message » categorize

7. Re: what am I missing?

mattlewis said...
jacques_desch said...

the extra byte is at end of allocated struct. Matt code give this on Linpus lite compiled with gcc 4.1.2

termios2: 44 
c_iflag:  0xbfc9e408 
c_oflag:  0xbfc9e40c 
c_cflag:  0xbfc9e410 
c_lflag:  0xbfc9e414 
c_line:   0xbfc9e418 
c_cc:     0xbfc9e419 
c_ispeed: 0xbfc9e42c 
c_ospeed: 0xbfc9e430 
So there is no padding between fields but allocationg 44 crash my program. Well I will take it as a mystery and go on with TERMIOS_SIZE=45

That's odd. What happens if you do the same in C? Meaning, can you malloc 44 bytes and not have it crash?

It sounds like the code is writing out of bounds somewhere. Actually, I'd recommend running it under valgrind, so see where the illegal access is happening. Sounds like a bug in the library. If you do any C coding on Linux, valgrind can be your best friend for tracking down weird memory issues.

Matt

Matt, Following you suggestion, here de C code I tested and it crash too, but only if I free t pointer. The same is true in my euphoria binding.

#include <stdio.h> 
#include <asm/termbits.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <stdlib.h> 
 
int main(){ 
int fd, fnVal; 
struct termios2 *t; 
  fd = open("/dev/tty0",O_RDONLY); 
  printf("file handle %d\n", fd); 
  t = malloc(sizeof(struct termios2)); 
  fnVal = tcgetattr(fd, t); 
  printf("ispeed %d, ospeed %d\n",t->c_ispeed, t->c_ospeed); 
  free(t); // it doesn't crash if I don't free t. 
  puts("t freed\n"); 
  close(fd); 
} 
 
 
Now the question is why freeing t, which is no more used, crash the program?

new topic     » goto parent     » topic index » view message » categorize

8. Re: what am I missing?

jacques_desch said...

Matt, Following you suggestion, here de C code I tested and it crash too, but only if I free t pointer. The same is true in my euphoria binding.

#include <stdio.h> 
#include <asm/termbits.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <stdlib.h> 
 
int main(){ 
int fd, fnVal; 
struct termios2 *t; 
  fd = open("/dev/tty0",O_RDONLY); 
  printf("file handle %d\n", fd); 
  t = malloc(sizeof(struct termios2)); 
  fnVal = tcgetattr(fd, t); 
  printf("ispeed %d, ospeed %d\n",t->c_ispeed, t->c_ospeed); 
  free(t); // it doesn't crash if I don't free t. 
  puts("t freed\n"); 
  close(fd); 
} 
 
 
Now the question is why freeing t, which is no more used, crash the program?

I think you're using the wrong header. See the man page, here.

Looks like the correct size is actually 60. Try this code:

#include <stdio.h>  
#include <termios.h>  
#include <fcntl.h>  
  
int main(){  
int fd, fnVal;  
struct termios *t;  
	printf("termios %d\n", sizeof( struct termios ) ); 
  fd = open("/dev/tty",O_RDONLY);  
  printf("file handle %d\n", fd);  
  t = malloc(sizeof(struct termios));  
  fnVal = tcgetattr(fd, t);  
  printf("fnVal %d ispeed %d, ospeed %d\n", fnVal, t->c_ispeed, t->c_ospeed); 
  free(t); // it doesn't crash if I don't free t.  
  puts("t freed\n");  
  close(fd);  
}  
Matt

new topic     » goto parent     » topic index » view message » categorize

9. Re: what am I missing?

mattlewis said...
jacques_desch said...

Matt, Following you suggestion, here de C code I tested and it crash too, but only if I free t pointer. The same is true in my euphoria binding.

#include <stdio.h> 
#include <asm/termbits.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <stdlib.h> 
 
int main(){ 
int fd, fnVal; 
struct termios2 *t; 
  fd = open("/dev/tty0",O_RDONLY); 
  printf("file handle %d\n", fd); 
  t = malloc(sizeof(struct termios2)); 
  fnVal = tcgetattr(fd, t); 
  printf("ispeed %d, ospeed %d\n",t->c_ispeed, t->c_ospeed); 
  free(t); // it doesn't crash if I don't free t. 
  puts("t freed\n"); 
  close(fd); 
} 
 
 
Now the question is why freeing t, which is no more used, crash the program?

I think you're using the wrong header. See the man page, here.

Looks like the correct size is actually 60. Try this code:

#include <stdio.h>  
#include <termios.h>  
#include <fcntl.h>  
  
int main(){  
int fd, fnVal;  
struct termios *t;  
	printf("termios %d\n", sizeof( struct termios ) ); 
  fd = open("/dev/tty",O_RDONLY);  
  printf("file handle %d\n", fd);  
  t = malloc(sizeof(struct termios));  
  fnVal = tcgetattr(fd, t);  
  printf("fnVal %d ispeed %d, ospeed %d\n", fnVal, t->c_ispeed, t->c_ospeed); 
  free(t); // it doesn't crash if I don't free t.  
  puts("t freed\n");  
  close(fd);  
}  
Matt

You got Matt, many Thanks.

new topic     » goto parent     » topic index » view message » categorize

10. Re: what am I missing?

I meant: You got it Matt...

new topic     » goto parent     » topic index » view message » categorize

11. Re: what am I missing?

I found the good definition of termios in <bits/termios.h> the only difference with termios2 is the NCCS which is 32 instead of 19 which give 57 bytes although sizeof() report 60, probably pad end of struct to align DWORD.

Jacques

new topic     » goto parent     » topic index » view message » categorize

12. Re: what am I missing?

A final comment on this thread. I finaly found where the padding is in the struct.
first the definition as per <bits/termios.h>:

typedef unsigned char   cc_t; 
typedef unsigned int    speed_t; 
typedef unsigned int    tcflag_t; 
 
#define NCCS 32 
struct termios 
  { 
    tcflag_t c_iflag;           /* input mode flags */ 
    tcflag_t c_oflag;           /* output mode flags */ 
    tcflag_t c_cflag;           /* control mode flags */ 
    tcflag_t c_lflag;           /* local mode flags */ 
    cc_t c_line;                        /* line discipline */ 
    cc_t c_cc[NCCS];            /* control characters */ 
    speed_t c_ispeed;           /* input speed */ 
    speed_t c_ospeed;           /* output speed */ 
#define _HAVE_STRUCT_TERMIOS_C_ISPEED 1 
#define _HAVE_STRUCT_TERMIOS_C_OSPEED 1 
  }; 
The catch here is that c_ispeed doesn't follow immedialely the c_cc[NCCS] array. There is 3 bytes of padding. It is why sizeof(struct termios) report 60 bytes.
Not nice for those who try to bind C code to hide such information.
Jacques

new topic     » goto parent     » topic index » view message » categorize

13. Re: what am I missing?

jacques_desch said...
SDPringle said...

You guys shouldn't be counting bytes. Use the sizeof() operator the C compiler will tell you how big the structure is.

I'm not writing C code but euphoria binding to termios, so sizeof() is of no use to me.

jacques

jacques_desch said...

The catch here is that c_ispeed doesn't follow immedialely the c_cc[NCCS] array. There is 3 bytes of padding. It is why sizeof(struct termios) report 60 bytes. Not nice for those who try to bind C code to hide such information. Jacques

Agreed. In general, I'd recommend writing a partical C wrapper in between the library and the part of the wrapper written in Euphoria, in the way Matt has a custom C library that wraps wxWidgets in C first before being wrapped in Eu, and the way Irv used to have a C library that wrapped parts of GTK (like the C macros which otherwise had to be ported by hand and then hardcoded in Eu) for euGTK.

In fact, I seem to recall that the C library wrapper for EuGTK specifically had functions that merely returned the value of a sizeof().

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu