Compiling a C program that used nanosleep
turned out to be quite the thorn in my side. I’m documenting this here for anyone else facing the same issues.
TL;DR — Try compiling your program with a GNU standard e.g. gcc -std=gnu11 ...
Debugging
Here’s a simplified version of what I was trying to compile.
// Compiled via: gcc -std=c99 main.c
#include <time.h>
int main() {
struct timespec sleep;
sleep.tv_sec = 0;
sleep.tv_nsec = 50000000;
nanosleep(&sleep, NULL);
}
I kept getting the following error and warning.
main.c: In function ‘main’:
main.c:4:21: error: storage size of ‘sleep’ isn’t known
struct timespec sleep;
^~~~~
main.c:7:5: warning: implicit declaration of function ‘nanosleep’ [-Wimplicit-function-declaration]
nanosleep(&sleep, NULL);
^~~~~~~~~
My initial googling only turned up the suggestion to define a POSIX source macro1 at the start of the file. This didn’t work for me.
Inspired by some obscure forum posts, I noticed that the program compiled when I removed the -std=c99
GCC option. Peculiar, why was that making it fail? To dig in I inspected the preprocessor output.
$ gcc -std=c99 -E main.c | grep timespec
struct timespec sleep;
$ gcc -E main.c | grep timespec
struct timespec
struct timespec it_interval;
struct timespec it_value;
extern int nanosleep (const struct timespec *__requested_time,
struct timespec *__remaining);
...
A grep of the C99 standard output only turned up the instance of timespec
used in main.c
. The default standard output had a timespec
struct, a nanosleep
declaration, and even more I’ve left out. These declarations resolved both the error and warning I was encountering.
Going Further
A fix, hooray! But, this left me with more questions than answers. First off, what standard does GCC use by default when we don’t select one? My machine is running GCC v7.5.0
and thanks to this helpful Stackoverflow answer we can see that GCC is defaulting to the GNU11 standard. So apparently time.h
from the GNU11 standard’s gives us what we need where as the time.h
from the C99 standard does not.
This begs the question of what other standards work. I tested a few of the common options and have placed the results below.
GNU89 / GNU99 / GNU11
No issues here. The nanosleep
function works flawlessly with all these standards.
C89 / C99
Both fail to compile with the all too familiar “storage size isn’t known error”. Neither standards include struct timespec
or nanosleep
. A fun tidbit is that the C89 standard does not trigger a warning for the implicit declaration of a function — this wasn’t part of the C language yet.
C11
C11 is something of an anomaly. It compiles successfully but still throws the implicit declaration error. However, we can quench this error by defining the POSIX source macro1 I mentioned earlier.
-
#define _POSIX_C_SOURCE 199309L
↩︎
Hey, if you’ve read this far you might like to join my email list.
I’ll email you any time I publish something new.
No spam or ads. Unsubscribe as your heart desires.
Error when building current develop branch on Ubuntu 18.04:
/bin/bash ../../libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I../../libsrc/Dk -fno-strict-aliasing -O2 -Wall -DNDEBUG -DPOINTER_64 -I/home/klimekj/virtuoso-opensource/libsrc/Xml.new -DOPENSSL_NO_KRB5 -Dlinux -D_GNU_SOURCE -DFILE64 -D_LARGEFILE64_SOURCE -I../../libsrc -I../../libsrc/Dk -I../../libsrc/zlib -I. -I../../libsrc/langfunc -I../../libsrc/plugin -I../../libsrc/Tidy -I../../libsrc/Xml.new -I../../libsrc/odbcsdk/include -DVAD -DDBP -DBIF_XPER -DOPSYS="Linux" -DHOST="x86_64-pc-linux-gnu" -g -O2 -MT libwi_la-bif_crypto.lo -MD -MP -MF .deps/libwi_la-bif_crypto.Tpo -c -o libwi_la-bif_crypto.lo `test -f 'bif_crypto.c' || echo './'`bif_crypto.c
libtool: compile: gcc -DHAVE_CONFIG_H -I. -I../../libsrc/Dk -fno-strict-aliasing -O2 -Wall -DNDEBUG -DPOINTER_64 -I/home/klimekj/virtuoso-opensource/libsrc/Xml.new -DOPENSSL_NO_KRB5 -Dlinux -D_GNU_SOURCE -DFILE64 -D_LARGEFILE64_SOURCE -I../../libsrc -I../../libsrc/Dk -I../../libsrc/zlib -I. -I../../libsrc/langfunc -I../../libsrc/plugin -I../../libsrc/Tidy -I../../libsrc/Xml.new -I../../libsrc/odbcsdk/include -DVAD -DDBP -DBIF_XPER -DOPSYS="Linux" -DHOST="x86_64-pc-linux-gnu" -g -O2 -MT libwi_la-bif_crypto.lo -MD -MP -MF .deps/libwi_la-bif_crypto.Tpo -c bif_crypto.c -fPIC -DPIC -o .libs/libwi_la-bif_crypto.o
bif_crypto.c: In function ‘box_hmac’:
bif_crypto.c:184:12: error: storage size of ‘ctx’ isn’t known
HMAC_CTX ctx;
^~~
bif_crypto.c:190:3: warning: ‘HMAC_Init’ is deprecated [-Wdeprecated-declarations]
HMAC_Init (&ctx, key, box_length (key) - DV_STRINGP (key) ? 1 : 0, md);
^~~~~~~~~
In file included from /usr/include/openssl/hmac.h:13:0,
from /usr/include/openssl/ssl.h:56,
from http.h:39,
from bif_crypto.c:37:
/usr/include/openssl/hmac.h:28:1: note: declared here
DEPRECATEDIN_1_1_0(__owur int HMAC_Init(HMAC_CTX *ctx, const void *key, int len,
^
bif_crypto.c:184:12: warning: unused variable ‘ctx’ [-Wunused-variable]
HMAC_CTX ctx;
^~~
bif_crypto.c: In function ‘asn1_parse_to_xml’:
bif_crypto.c:351:13: warning: implicit declaration of function ‘d2i_ASN1_BOOLEAN’; did you mean ‘V_ASN1_BOOLEAN’? [-Wimplicit-function-declaration]
ii = d2i_ASN1_BOOLEAN (NULL, (const unsigned char **)&opp, len + hl);
^~~~~~~~~~~~~~~~
V_ASN1_BOOLEAN
bif_crypto.c:418:5: warning: implicit declaration of function ‘M_ASN1_OCTET_STRING_free’; did you mean ‘ASN1_OCTET_STRING_free’? [-Wimplicit-function-declaration]
M_ASN1_OCTET_STRING_free (os);
^~~~~~~~~~~~~~~~~~~~~~~~
ASN1_OCTET_STRING_free
bif_crypto.c:451:8: warning: implicit declaration of function ‘M_ASN1_INTEGER_free’; did you mean ‘ASN1_INTEGER_free’? [-Wimplicit-function-declaration]
M_ASN1_INTEGER_free (bs);
^~~~~~~~~~~~~~~~~~~
ASN1_INTEGER_free
bif_crypto.c:482:8: warning: implicit declaration of function ‘M_ASN1_ENUMERATED_free’; did you mean ‘ASN1_ENUMERATED_free’? [-Wimplicit-function-declaration]
M_ASN1_ENUMERATED_free (bs);
^~~~~~~~~~~~~~~~~~~~~~
ASN1_ENUMERATED_free
bif_crypto.c: In function ‘bio_to_strses’:
bif_crypto.c:726:33: error: dereferencing pointer to incomplete type ‘BIO {aka struct bio_st}’
to_free = ((BUF_MEM *) out_bio->ptr)->data;
^~
bif_crypto.c: In function ‘bif_smime_sign’:
bif_crypto.c:927:21: error: dereferencing pointer to incomplete type ‘X509_STORE {aka struct x509_store_st}’
if (store && store->objs)
^~
bif_crypto.c:932:11: error: dereferencing pointer to incomplete type ‘X509_OBJECT {aka struct x509_object_st}’
if (obj->type == X509_LU_X509)
^~
bif_crypto.c: In function ‘x509_certificate_verify_cb’:
bif_crypto.c:1184:18: error: dereferencing pointer to incomplete type ‘X509_STORE_CTX {aka struct x509_store_ctx_st}’
switch (ctx->error)
^~
bif_crypto.c: In function ‘BN_box’:
bif_crypto.c:1317:37: error: dereferencing pointer to incomplete type ‘BIGNUM {aka struct bignum_st}’
buf = box_num ((unsigned long) x->d[0]);
^~
bif_crypto.c: In function ‘bif_get_certificate_info’:
bif_crypto.c:1501:41: error: dereferencing pointer to incomplete type ‘X509 {aka struct x509_st}’
STACK_OF (X509_EXTENSION) * exts = cert->cert_info->extensions;
^~
bif_crypto.c:1513:5: warning: implicit declaration of function ‘M_ASN1_OCTET_STRING_print’; did you mean ‘ASN1_OCTET_STRING_set’? [-Wimplicit-function-declaration]
M_ASN1_OCTET_STRING_print (mem, ex->value);
^~~~~~~~~~~~~~~~~~~~~~~~~
ASN1_OCTET_STRING_set
bif_crypto.c:1513:39: error: dereferencing pointer to incomplete type ‘X509_EXTENSION {aka struct X509_extension_st}’
M_ASN1_OCTET_STRING_print (mem, ex->value);
^~
bif_crypto.c:1540:11: error: dereferencing pointer to incomplete type ‘EVP_PKEY {aka struct evp_pkey_st}’
if (k->type == EVP_PKEY_RSA)
^~
bif_crypto.c:1543:65: error: dereferencing pointer to incomplete type ‘RSA {aka struct rsa_st}’
ret = list (3, box_dv_short_string ("RSAPublicKey"), BN_box (x->e), BN_box (x->n));
^~
bif_crypto.c:1551:65: error: dereferencing pointer to incomplete type ‘DSA {aka struct dsa_st}’
ret = list (2, box_dv_short_string ("DSAPublicKey"), BN_box (x->pub_key));
^~
bif_crypto.c:1570:61: error: dereferencing pointer to incomplete type ‘X509_NAME {aka struct X509_name_st}’
for (i = 0; NULL != subj && i < sk_X509_NAME_ENTRY_num(subj->entries); i++)
^~
bif_crypto.c:1573:25: error: dereferencing pointer to incomplete type ‘X509_NAME_ENTRY {aka struct X509_name_entry_st}’
n = OBJ_obj2nid (ne->object);
^~
bif_crypto.c: In function ‘bif_base36dec’:
bif_crypto.c:1819:16: warning: initialization makes integer from pointer without a cast [-Wint-conversion]
boxint str = bif_string_arg (qst, args, 0, "base36dec");
^~~~~~~~~~~~~~
bif_crypto.c:1821:17: warning: passing argument 1 of ‘strtoul’ makes pointer from integer without a cast [-Wint-conversion]
ret = strtoul(str, NULL, 36);
^~~
In file included from ../../libsrc/odbcsdk/include/iodbcunix.h:79:0,
from ../../libsrc/odbcsdk/include/sql.h:87,
from odbcinc.h:72,
from sqlnode.h:31,
from bif_crypto.c:28:
/usr/include/stdlib.h:180:26: note: expected ‘const char * restrict’ but argument is of type ‘boxint {aka long long int}’
extern unsigned long int strtoul (const char *__restrict __nptr,
^~~~~~~
Makefile:1306: recipe for target 'libwi_la-bif_crypto.lo' failed
make[3]: *** [libwi_la-bif_crypto.lo] Error 1
make[3]: Leaving directory '/home/klimekj/virtuoso-opensource/libsrc/Wi'
Makefile:2988: recipe for target 'install' failed
make[2]: *** [install] Error 2
make[2]: Leaving directory '/home/klimekj/virtuoso-opensource/libsrc/Wi'
Makefile:477: recipe for target 'install-recursive' failed
make[1]: *** [install-recursive] Error 1
make[1]: Leaving directory '/home/klimekj/virtuoso-opensource/libsrc'
Makefile:633: recipe for target 'install-recursive' failed
make: *** [install-recursive] Error 1
- Forum
- General Programming Boards
- C Programming
- compile error: storage size of ‘var’ isn’t known
-
03-28-2007
#1
Registered User
compile error: storage size of ‘var’ isn’t known
Hello everyone,
I get a strange compile error when compile such simple program. Any ideas?
foo.c: In function `main’:
foo.c:5: error: storage size of ‘var’ isn’t knownfoo.c
Code:
#include "goo.h" int main (int argc, char** argv) { t_st var; var.member = 100; return 0; }
goo.c
Code:
struct st { int member; };
goo.h
Code:
typedef struct st t_st;
thanks in advance,
George
-
03-28-2007
#2
Registered User
So how did you compile your program. did you linked your library with your main program while compiling.
ssharish2005
-
03-28-2007
#3
Officially An Architect
You define the structure in a .c file. How can any other module possibly know about it?
Both the structure and the typedef should be in goo.h, and there should be no file goo.c.
-
03-28-2007
#4
and the hat of int overfl
Well goo.c has the actual structure, so there is no way for foo.c to know what the members are.
All that goo.h does is basically confirm that a struct called st exists.
In foo.c, you could have
t_st *var;
but you still would not be able to access any members within that struct.It is, in other words an incomplete type.
Incomplete types are very useful for implementing opaque interfaces. goo.h declares an opaque pointer, which any user just sees the pointer.
The actual content of the struct is private to goo.c.It’s what FILE* should be — all user code just passes around a FILE* without ever knowing what is behind it.
-
04-02-2007
#5
Registered User
Definitely, yes! Any ideas?
Originally Posted by ssharish2005
So how did you compile your program. did you linked your library with your main program while compiling.
ssharish2005
regards,
George
-
04-02-2007
#6
Registered User
Thanks, do you mean any structure definition (real implementation) must be in .h in C? I have seen many program written by others which define (implement) struct in .c other than .h.
Originally Posted by brewbuck
You define the structure in a .c file. How can any other module possibly know about it?
Both the structure and the typedef should be in goo.h, and there should be no file goo.c.
regards,
George
-
04-02-2007
#7
Registered User
Thanks Salem, do you mean in order to access the member of a struct, we have to define struct in .h and includes it, or else we could only access its member variable inside the same .c file? No walk-arounds?
Originally Posted by Salem
Well goo.c has the actual structure, so there is no way for foo.c to know what the members are.
All that goo.h does is basically confirm that a struct called st exists.
In foo.c, you could have
t_st *var;
but you still would not be able to access any members within that struct.It is, in other words an incomplete type.
Incomplete types are very useful for implementing opaque interfaces. goo.h declares an opaque pointer, which any user just sees the pointer.
The actual content of the struct is private to goo.c.It’s what FILE* should be — all user code just passes around a FILE* without ever knowing what is behind it.
regards,
George
-
04-02-2007
#8
and the hat of int overfl
Yes.
For direct access, you need the structure name and its members in scope.
-
04-02-2007
#9
Registered User
Hey,
Can u use resource of any person to whom u dont know.
Same is happening here. Ur program knows goo.h and goo.h has no information about goo.c. even foo.c knows nothing about goo.c. So how can foo.c access goo.c resource.S_ccess is waiting for u. Go Ahead, put u there.
-
04-03-2007
#10
and the hat of int overfl
Is it so hard to use English rather than that cryptic «kiddie» speak?
Popular pages
- Exactly how to get started with C++ (or C) today
- C Tutorial
- C++ Tutorial
- 5 ways you can learn to program faster
- The 5 Most Common Problems New Programmers Face
- How to set up a compiler
- 8 Common programming Mistakes
- What is C++11?
- Creating a game, from start to finish
Recent additions
- How to create a shared library on Linux with GCC — December 30, 2011
- Enum classes and nullptr in C++11 — November 27, 2011
- Learn about The Hash Table — November 20, 2011
- Rvalue References and Move Semantics in C++11 — November 13, 2011
- C and C++ for Java Programmers — November 5, 2011
- A Gentle Introduction to C++ IO Streams — October 10, 2011
Similar Threads
-
Replies: 26
Last Post: 10-19-2008, 08:51 PM
-
Replies: 5
Last Post: 04-06-2005, 01:20 PM
-
Replies: 24
Last Post: 01-21-2004, 01:12 AM
-
Replies: 5
Last Post: 02-15-2002, 09:24 AM
-
Replies: 4
Last Post: 12-15-2001, 08:03 PM