Friday, July 22, 2011

'format' attribute in gcc

We can check the format of a function against the set of arguments using 'format' attribute. This is is very much useful when we write our own logger function. The format attributes check for the format of a particular function against format of predefined function. The index of format and the variable arguments in the function have to be passed into the attribute.

Ex: void log_inline(const char* format, ...) __attribute__((format(printf,1,2)));

The format of log_inline is checked against the printf function. The format that has to be checked is the first argument of log_inline, while arguments start with second position of log_inline. This is specified as (1,2) in format attribute.

There is an example program:

#include<stdio.h>
#include<stdarg.h>

void log_inline(const char* format, ...) __attribute__((format(printf,1,2)));

void log_inline(const char* format, ...)
{
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
}

int main()
{
log_inline("%s\n", "SOMETHING");
log_inline("%s\n",1); //Generates warning message
}

We need to compile with -Wall option of gcc to identify the warning.

Note that without attribute in function declaration, warning is not produced.

Saturday, July 2, 2011

World IPv6 day.

8th June 2011 was world ipv6 day. If you refer the link "http://www.worldipv6day.org/", it says many of the companies (including linux kernel site) did switch to ipv6 stack to have global scale trial. If you refer the resource section, some countries have their own ipv6 day. Hope India will also have one in future. The event passed on without making any news at-least to me!! Here is the logo



WORLD IPV6 DAY is 8 June 2011 – The Future is Forever

May be every year this event happens however this is first time I am noticing though; roughly a month after event passed off!!

Monday, June 13, 2011

'warn_unused_result' attribute in gcc

If you want to enforce checking return value of your function you can specify warn_unused_result attribute in your function declaration (ofcourse attributes can be placed only in declarations not definitions). If this attibute is specified and caller does not check the return value, the compiler outputs warning message for not checking return value. This does not mean you need to check the return value but bare assignment also removes this warning. Ofcourse it is difficult as well as ugly to check against condition. Warning is well sufficient. Here is an example. Using this attribute in void function has no effect. gcc simply ignores the attribute and same is displayed in compilation output.

int check() __attribute__((warn_unused_result));
int check()
{
return 0;
}

int main()
{
check();
/*
compiler warns of not checking return value --
warning: ignoring return value of check,
declared with attribute warn_unused_result
*/

int k = check();//no warning
}

Saturday, June 11, 2011

Achieivng memcpy and memmove in single function

Somebody asked me is it possible to simulate memcpy and memmove in a single function. Initially I did not get it. I thought for a while and finally came up with the following solution. This is quite crude code however satisfies the functionality. glibc expects that for memcpy, pointers should not overlap even after copying. If they overlap, then memmove must be used.

As shown in figure there are three cases



Here:

s = source pointer
d = destination pointer
b = boundary
size = number of bytes to copy

1) d >= s+size
2) d < s
3) d < s+size

If d=s, we do not do anything. simply return

The cases 1 and 2 are trivial. In the sense, plain copying does not corrupt destination 'd' buffer. However in case '2', source 's' data will be modified.
The problem is with case 3. When we do plain copy, the source data buffer at the tail gets corrupted and destination 'd' will not have replica of source 's'. We can avoid this by copying from the last i.e. copy from 's+size' to 'd+size' and move towards 's' and 'd'.

Here is the program. The example may be trivial however I hope this works.

#include<stdio.h>

void my_memcpy(void* src, void* dst, size_t bytes);

void my_memcpy(void* src, void* dst, size_t bytes)
{
unsigned char* s = (unsigned char*)src;
unsigned char* d = (unsigned char*)dst;

if(s == d)
{
//same
return;
}

size_t k = 0;
if(s+bytes > d)
{
//Overlapping
k = bytes;
while(k > 0)
{
d[k-1] = s[k-1];
k--;
}
return;
}

//Other cases
while(k < bytes)
{
d[k] = s[k];
k++;
}
}

int main()
{
int i[10] = {0x1234, 0x2345, 0x3456, 0x4567};
my_memcpy(i, &i[2], sizeof(int) * 4);
int j = 0;
for(;j<6;j++)
printf("%x\n", i[j]);
}


When I browsed through glibc code, it used page copy technique in case of memcpy. It tries to get page boundary and copies data in pages. This technique is quite faster for huge data. For data which are not page aligned, it does plain copy. For i386, seems like it uses inline assembly.

Thursday, June 9, 2011

'weak' attribute in gcc

Recently I came to know about gcc attributes which can be used in code for specific purpose. One of them I understood early was 'weak' attribute. A 'weak' attribute may be specified if you don want compiler to throw any error if it was unable to resolve external symbols. This is useful if you are planning to provide function or variable in near future and do not want to modify the main source at that time.

#include<stdio.h>

extern int k() __attribute__((weak));
extern int k2 __attribute__((weak));

int main()
{
if(k == NULL)
{
if(&k2 == NULL)
{
printf("No symbol k or k2 found\n");
}
}
else
{
k();
}
}

This example compiles just fine and gives no linkage error even if the symbols are not found. However if we are using those symbols we need to check NULLness of those symbols else the program will result in seg fault.

Sunday, May 29, 2011

Casting away consts in C++

This could be dangerous sometimes. Stroustrup in his book has noted that const variables may be put in read only section of the memory. Hence casting away their consts and modifying them definitely lead to memory access violation. A small example can be like this.

#include <iostream>
#include <string.h>

const char val[] = {"Test1"};

void bad_modify(char* str, char* str2, const size_t len)
{
memcpy(str, str2, len);
}

int main()
{
char* s = "Value";
char* p = const_cast
<char*>(val);
bad_modify(p, s, 5);
std::cout<
<p<<std::endl;
}


g++ puts the varibale val in readonly section of the memory.
Hence when we cast away const from val and try to modify it, we get segmentation fault.

Comments are always welcome