Why are linux's IPv4 address taking 16 bytes instead of 4 - c++

I'm trying to resolve a domain name to an ipv4 address.
Here's a minimal code of what I'm doing
addrinfo hints, *results;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
int error = getaddrinfo("google.com", 0, &hints, &results);
for(addrinfo* info = results; info; info = info->ai_next)
{
std::cout << (info->ai_family == AF_INET6 ? "ip6" : "ip4")
<< '[' << info->ai_addrlen << "]: ";
for(uint i = 0; i < info->ai_addrlen; ++i)
std::cout << int(((uint8_t*)info->ai_addr)[i]) << ' ';
std::cout << std::endl;
}
freeaddrinfo(results);
When I run this, it prints:
ip4[16]: 2 0 0 0 216 58 208 238 0 0 0 0 0 0 0 0
ip4[16]: 2 0 0 0 216 58 208 238 0 0 0 0 0 0 0 0
ip4[16]: 2 0 0 0 216 58 208 238 0 0 0 0 0 0 0 0
The actual ip of google.com is 216.58.208.238. So for some reason, for ip v4, ai_addr contains 16 bytes and actually stores the address at bytes 4 to 8.
My question is: what are the 12 other bytes for ?
I read the docs, and googled a bit but found nothing on addr_len. Also note that I didn't set the AI_V4MAPPED flag.

I'm not sure whether this is actually required by some standard, but struct sockaddr is defined to contain a short for the address family and then 14 bytes of address-family-specific data.
Every type used as an address must be compatible with that, thus, be at least the same length.
For struct sockaddr_in (the one for IPv4), it looks like this:
struct sockaddr_in {
short sin_family;
unsigned short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
2 bytes for the address family, 2 bytes for the port, 4 bytes for the IPv4 address and 8 bytes of padding to reach the length of struct sockaddr.
That said: Your question is slightly wrong, this is not an IPv4 address (that would be just struct in_addr which is indeed just 4 bytes) but a socket address for IPv4. Still, 8 bytes are "wasted" here.

Related

Why does Microsoft's implementation of std::string require 40 bytes on the stack?

Having recently watched this video about facebook's implementation of string, I was curious to see the internals of Microsoft's implementation. Unfortunately, the string file (in %VisualStudioDirectory%/VC/include) doesn't seem to contain the actual definition, but rather just conversion functions (e.g. atoi) and some operator overloads.
I decided to do some poking and prodding at it from user-level programs. The first thing I did, of course, was to test sizeof(std::string). To my surprise, std::string takes 40 bytes! (On 64-bit machines anyways.) The previously mentioned video goes into detail about how facebook's implementation only requires 24 bytes and gcc's takes 32 bytes, so this was shocking to say the least.
We can dig a little deeper by writing a simple program that prints off the contents of the data byte-by-byte (including the c_str address), as such:
#include <iostream>
#include <string>
int main()
{
std::string test = "this is a very, very, very long string";
// Print contents of std::string test.
char* data = reinterpret_cast<char*>(&test);
for (size_t wordNum = 0; wordNum < sizeof(std::string); wordNum = wordNum + sizeof(uint64_t))
{
for (size_t i = 0; i < sizeof(uint64_t); i++)
std::cout << (int)(data[wordNum + i]) << " ";
std::cout << std::endl;
}
// Print the value of the address returned by test.c_str().
// (Doing this byte-by-byte to match the above values).
const char* testAddr = test.c_str();
char* dataAddr = reinterpret_cast<char*>(&testAddr);
std::cout << "c_str address: ";
for (size_t i = 0; i < sizeof(const char*); i++)
std::cout << (int)(dataAddr[i]) << " ";
std::cout << std::endl;
}
This prints out:
48 33 -99 -47 -55 1 0 0
16 78 -100 -47 -55 1 0 0
-52 -52 -52 -52 -52 -52 -52 -52
38 0 0 0 0 0 0 0
47 0 0 0 0 0 0 0
c_str address: 16 78 -100 -47 -55 1 0 0
Examining this, we can see that the second word contains the address that points to the allocated data for the string, the third word is garbage (a buffer for Short String Optimization), the fourth word is the size, and the fifth word is the capacity. But what about the first word? It appears to be an address, but what for? Shouldn't everything already be accounted for?
For the sake of completeness, the following output shows SSO (the string is set to "Short String"). Note that the first word still seems to represent a pointer:
0 36 -28 19 123 1 0 0
83 104 111 114 116 32 83 116
114 105 110 103 0 -52 -52 -52
12 0 0 0 0 0 0 0
15 0 0 0 0 0 0 0
c_str address: 112 -9 79 -108 23 0 0 0
EDIT: Ok, so having done more testing, it appears that the size of std::string actually decreases down to 32 bytes when compiled for release, and the first word is no longer there. But I'm still really interested in knowing why that is the case, and what that extra pointer is used for in debug mode.
Update: As per the tip by the user Yuushi, the extra word appears to related to Debug Iterator Support. This was verified when I turned off Debug Iterator Support (an example for doing this is shown here) and the size of std::string was reduced to 32 bytes, with the first word now missing.
However, it would still be really interesting to see how Debug Iterator Support uses that additional pointer to check for incorrect iterator use.
Visual Studio 2015 use xstring instead of string to define std::basic_string
NOTE: This answer is applied for VS2015 only, VS2013 uses a different implementation, however, they are more or less the same.
It's implemented as:
template<class _Elem,
class _Traits,
class _Alloc>
class basic_string
: public _String_alloc<_String_base_types<_Elem, _Alloc> >
{
// This class has no member data
}
_String_alloc use a _Compressed_pair<_Alty, _String_val<_Val_types> > to store its data, in std::string, _Alty is std::allocator<char> and _Val_types is _Simple_types<char>, because std::is_empty<std::allocator<char>>::value is true, sizeof _Compressed_pair<_Alty, _String_val<_Val_types> > is the same with sizeof _String_val<_Val_types>
class _String_val inherites from _Container_base which is a typedef of _Container_base0 when #if _ITERATOR_DEBUG_LEVEL == 0 and _Container_base12 otherwise. The difference between them is _Container_base12 contains pointer to _Container_proxy for debug purpose. Beside that _String_val also have those members:
union _Bxty
{ // storage for small buffer or pointer to larger one
_Bxty()
{ // user-provided, for fancy pointers
}
~_Bxty() _NOEXCEPT
{ // user-provided, for fancy pointers
}
value_type _Buf[_BUF_SIZE];
pointer _Ptr;
char _Alias[_BUF_SIZE]; // to permit aliasing
} _Bx;
size_type _Mysize; // current length of string
size_type _Myres; // current storage reserved for string
With _BUF_SIZE is 16.
And pointer_type, size_type is well aligned together in this system. No alignment is necessary.
Hence, when _ITERATOR_DEBUG_LEVEL == 0 then sizeof std::string is:
_BUF_SIZE + 2 * sizeof size_type
otherwise it's
sizeof pointer_type + _BUF_SIZE + 2 * sizeof size_type

boost serialization hexadecimal decimal encoding of data

I am new to boost serialization but this seems very strange to me.
I have a very simple class with two members
int number // always = 123
char buffer[?] // buffer with ? size
so sometimes I set the size to buffer[31] then I serialize the class
22 serialization::archive 8 0 0 1 1 0 0 0 0 123 0 0 31 0 0 0 65 65
we can see the 123 and the 31 so no issue here both are in decimal format.
now I change buffer to buffer[1024] so I expected to see
22 serialization::archive 8 0 0 1 1 0 0 0 0 123 0 0 1024 0 0 0 65 65 ---
this is the actual outcome
22 serialization::archive 8 0 0 1 1 0 0 0 0 123 0 0 0 4 0 0 65 65 65
boost has switched to hex for the buffer size only?
notice the other value is still decimal.
So what happens if I switch number from 123 to 1024 ?
I would imagine 040 ?
22 serialization::archive 8 0 0 1 1 0 0 0 0 1024 0 0 0 4 0 0 65 65
If this is by design, why does the 31 not get converted to 1F ? its not consistent.
This causes problems in our load function for the split_free, we were doing this
unsigned int size;
ar >> size;
but as you might guess, when this is 040, it truncs to zero :(
what is the recommended solution to this?
I was using boost 1.45.0 but I tested this on boost 1_56.0 and it is the same.
EDIT: sample of the serialization function
template<class Archive>
void save(Archive& ar, const MYCLASS& buffer, unsigned int /*version*/) {
ar << boost::serialization::make_array(reinterpret_cast<const unsigned char*>(buffer.begin()), buffer.length());
}
MYCLASS is just a wrapper on a char* with the first element an unsigned int
to keep the length approximating a UNICODE_STRING
http://msdn.microsoft.com/en-gb/library/windows/desktop/aa380518(v=vs.85).aspx
The code is the same if the length is 1024 or 31 so I would not have expected this to be a problem.
I don't think Boost "switched to hex". I honestly don't have any experience with this, but it looks like boost is serializing as an array of bytes, which can only hold numbers from 0 through 255. 1024 would be a byte with a value 4 followed by a byte with the value 0.
"why does the 31 not get converted to 1F ? its not consistent" - your assumptions are creating false inconsistencies. Stop assuming you can read the serialization archive format when actually you're just guessing.
If you want to know, trace the code. If not, just use the archive format.
If you want "human accessible form", consider the xml_oarchive.

Storing integers in char*

I am a beginner is c trying something out. How can i pass an integer array to a function expecting char* in c/c++, since the range of char is only -128 to 127 but i want to store numbers from whole range of integers.
Here is what I was trying:
#include<stdlib.h>
#include<stdio.h>
int size = 12;
void print(char* array){
int i,j;
for(i=0;i<size;i++)
for(j=0;j<size;j++)
printf("%d ",*(array+i*size+j));
printf("\n");
}
int main(){
int array[size][size];
int i=0,j=0,k=0;
for(i=0;i<size;i++)
for(j=0;j<size;j++)
array[i][j]=k++;
for(i=0;i<size;i++)
for(j=0;j<size;j++)
printf("%d ",array[i][j]);
printf("\n");
print((char *) array);
return 0;
}
When array is printed inside the main function, the output is correct (numbers 0-143) but inside the print() function, the output is
0 0 0 0 1 0 0 0 2 0 0 0 3 0 0 0 4 0 0 0 5 0 0 0 6 0 0 0 7 0 0 0 8 0 0
0 9 0 0 0 10 0 0 0 11 0 0 0 12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0 16 0 0
0 17 0 0 0 18 0 0 0 19 0 0 0 20 0 0 0 21 0 0 0 22 0 0 0 23 0 0 0 24 0
0 0 25 0 0 0 26 0 0 0 27 0 0 0 28 0 0 0 29 0 0 0 30 0 0 0 31 0 0 0 32
0 0 0 33 0 0 0 34 0 0 0 35 0 0 0
I don't know what am I doing wrong.
P.S. I need this since I am using apache Zookeeper and the set and get functions it has require arguments of type char* for your data.
The same way you can use any array or pointer when using e.g. send for sockets: You cast the pointer.
Like
int data[DATA_SIZE];
...
send(s, (const char *) data, sizeof(data), 0);
This is very common, as many functions takes pointer to char even for generic data. The big question is what the function does with the data.
C and C++ are different languages.
"Integer array" is not a C type. Please be specific, such as:
int my_array[42];
You don't pass arrays, in C. Unless it is the operand of the sizeof, unary & or _Alignof operators, or is being used as an initializer, an expression with an array type evaluates to the value of a pointer to the first element of the array. Please see "Array Decay" at http://www.iso-9899.info/wiki/Code_snippets
In C, you can always cast a pointer to any complete or incomplete object type to a pointer to char *. int * is a pointer to a complete object type. Knowing these facts, the following code is valid, inside a function body:
int my_array[42];
char * what_i_want;
what_i_want = (char *) my_array;
Then you can pass the 'what_i_want' value to any function accepting a char * argument.
Having said this, you need to understand what the function is expecting. Share the function and some actual code, then perhaps someone will be able to offer greater insight as to how to achieve your goal.
char * can also be used to point to a string, so you can try using the appropriate conversion (int -> string, string -> int) functions to pass these.
If you post code, I can try and provide a more detailed answer.
Char* - it's the only type of pointer, but you can provide this function everything you want.
You can do something like that:
void func(char* aPointer)
{
int* arr = (int*)aPointer;
int firstInt = *arr;
...
}
Of course, this is very brutal way, so in this case you should be very careful, do some checks and so on.
void func(char* c)
{
...
}
int x[5] = {1,2,3,4,5};
func((char*)x);

How Can get the interface list in C++ in linux ?

I want to get my internet interface list in C++ in linux because my program need to down Or up the link but i dont know how get the interface to modifi it.
The system call you are looking for is getifaddrs. There is a brief example program on the man page.
Within the ifaddrs there is a bit flag field ifa_flags with which you can test whether the interface is up or down.
Read from /proc/net/dev
Full description in man proc:
/proc/net/dev
The dev pseudo-file contains network device status information. This gives the number of received and sent packets,
the number of errors and collisions and other basic statistics. These are used by the ifconfig(8) program to report
device status. The format is:
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
lo: 2776770 11307 0 0 0 0 0 0 2776770 11307 0 0 0 0 0 0
eth0: 1215645 2751 0 0 0 0 0 0 1782404 4324 0 0 0 427 0 0
ppp0: 1622270 5552 1 0 0 0 0 0 354130 5669 0 0 0 0 0 0
tap0: 7714 81 0 0 0 0 0 0 7714 81 0 0 0 0 0 0
This is a text file, each interface is a line... should be easy.
For example (no error checking... just printing the interface names)
#include <fstream>
#include <iostream>
int main() {
std::ifstream in("/proc/net/dev");
int c=0;
std::string line;
for(; std::getline( in, line ); c++)
{
if(c<2) continue; // skip header
std::size_t start=line.find_first_not_of(" "); // skip leading spaces
std::size_t end=line.find_first_of(":",start); // look for the ":"
std::cout << line.substr(start,end-start) << std::endl;
}
}

c++ reading (.cso) compiled shader object returning \0

I've tried two different methods to read from this cso file. Which is microsofts compiled shader
HRESULT BasicReader::ReadData(_In_z_ wchar_t const* fileName, _Inout_ std::unique_ptr<uint8_t[]>& data, _Out_ size_t* dataSize) {
ScopedHandle hFile(safe_handle(CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr)));
LARGE_INTEGER fileSize = { 0 };
FILE_STANDARD_INFO fileInfo;
GetFileInformationByHandleEx(hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo));
fileSize = fileInfo.EndOfFile;
data.reset(new uint8_t[fileSize.LowPart]);
DWORD bytesRead = 0;
ReadFile(hFile.get(), data.get(), fileSize.LowPart, &bytesRead, nullptr);
*dataSize = bytesRead;
}
GetFileInformationByHandleEx returned true
and ReadFile returned true
HRESULT BasicReader::ReadData(_In_z_ wchar_t const* fileName, _Inout_ std::unique_ptr<uint8_t[]>& data, _Out_ size_t* dataSize) {
std::ifstream fstream;
fstream.open(fileName, std::ifstream::in | std::ifstream::binary);
if (fstream.fail())
return false;
char* val;
fstream.seekg(0, std::ios::end);
size_t size = size_t(fstream.tellg());
val = new char[size];
fstream.seekg(0, std::ios::beg);
fstream.read(val, size);
fstream.close();
auto f = reinterpret_cast<unsigned char*>(val);
data.reset(f);
*dataSize = size;
}
Both of these methods make data = \0
However; when I point to another file in the same directory, it gives me data. What is happening here?
Here's the file.
I read the first few bytes of the file and it's this:
0 2 254 255 254 255 124 1 68 66 85 71 40 0 0 0 184 5 0 0 0 0 0 0 1 0 0 0 144 0 0
0 72 0 0 0 148 0 0 0 4 0 0 0 104 5 0 0 212 2 0 0 67 58 92 85 115 101 114 115 92
106 97 99 111 98 95 48 48 48 92 68 111 99 117 109 101 110 116 115 92 86 105 115
117 97 108 32 8...
And the working file looks like this:
68 68 83 32 124 0 0 0 7 16 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
32 0 0 0 0 64 0 0 0 0 0 0 0 32 0 0 0 0 0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 16
0 0 0 0 0 0 0 0 0 0...
Your code working as expected: char* data array contains file's data. What's going wrong here is that your char* data array is misinterpreted by your visualizers (whatever you use to visualize: debugger visualizer, std::cout, etc). They all try to print null-terminated (c-style) string, but it terminates instantly, as first char is 0. Raw arrays can also be visualized in debuggers as pointers: address and only first data member's value (because it cannot know where array ends). In C# situation is different as arrays are objects there, much like std::vectors, so their size is known.
Offtopic (sorry for that):
I would like to comment your second, native C++ BasicReader::ReadData method implementation, as it hurts my C++ feelings ;) You trying to write C code in C++11 style. "There is more than one way to skin a cat", but there are some advices:
don't use raw pointers (char*), use STL containers instead (std::vector, std::string)
have you really good reason to use std::unique_ptr<uint8_t[]> data + size_t dataSize instad of std::vector<uint8_t>?
avoid using raw operator new(), use STL containers, std::make_shared, std::make_unique (if available)
seekg()+tellg() file size counting can report wrong size in case of big files
Doesn't this code looks a little cleaner and more safe:
std::vector<uint8_t> ReadData(const std::string filename)
{
std::vector<uint8_t> data;
std::ifstream fs;
fs.open(filename, std::ifstream::in | std::ifstream::binary);
if (fs.good())
{
auto size = FileSize(filename);
// TODO: check here if size is more than size_t
data.resize(static_cast<size_t>(size));
fs.seekg(0, std::ios::beg);
fs.read(reinterpret_cast<char*>(&data[0]), size);
fs.close();
}
return data;
}
And usage is even more cleaner:
std::vector<uint8_t> vertexShaderData = ReadData("VertexShader.cso");
if(vertexShaderData.empty()) { /* handle it*/ }
auto wannaKnowSize = vertexShaderData.size();
As a bonus, you got a nice-looking debugger visualization.
And safe FileSize() implementation. You can use either boost::filesystem, of std::tr2 if your STL had implemented it.
#include <filesystem>
namespace filesystem = std::tr2::sys;
/* or namespace filesystem = boost::filesystem */
uintmax_t FileSize(std::string filename)
{
filesystem::path p(filename);
if (filesystem::exists(p) && filesystem::is_regular_file(p))
return filesystem::file_size(p);
return 0;
}
Hope it helps somehow.