tags:

views:

359

answers:

10

Possible Duplicates:
What is Type-safe?
What is type-safety?

I was reading about c++ vectors and it was mentioned that memcpy and printf functions from C are not type safe. Article here: http://en.wikipedia.org/wiki/Vector_(C%2B%2B).

Question: In simple English, what is type safety and what are the "type safe" alternatives?

+5  A: 

Type safety means that the compiler can check whether you're using the right types. For example, if you're using printf, you could accidentally crash your program by writing this:

printf("The meaning of life is %s", 42);

because 42 is an integer, not a string.

Chris Jester-Young
A: 

Since you were on Wikipedia anyway: Type safety.

Type safety means, roughly speaking, that the language prohibits you from accidentally mixing up your types.

memcpy is not type-safe because you can easily copy the memory of some int into a char array and end up with meaningless data. printf is not type safe because you can provide a %i format specifier with a string; again, the string will be interpreted as an int and you'll end up with garbage. (Incidentally, the VC++ compiler does check the format string in some situations.)

std::vector<T> is type-safe, because it only allows you to put values of the given type T into it. (You can do explicit typecasts, of course, but the point is that you have to be explicit about doing something that's not type safe).

Thomas
I would like to know why this was downvoted. Did I say something wrong?
Thomas
A: 

"Type safety" means that the compiler checks that you are doing the right things with the right types (e.g triggers a compiler error if you attempt to treat a Banana as an Orange, or give a string to a function expecting to output an integer).

Type safety (mostly) goes right out of the window when void* comes into the picture - it is a pointer that can point to anything (completely unaware of the types involved), and the language leaves going about with it completely in the programmers hands (for example, a void* isn't mostly good for anything except for being cast back to the original type; it can represent anything, but you have to know what it is before you can use it).

Type unsafety also comes to play with variadic functions like printf (the compiler doesn't care how many arguments there are and what their types are - again it is up to the caller to make sure that the format string matches the arguments and their types).

Type-safe alternative to memcpy (for arrays and containers) could be std::copy in <algorithm> - it may be implemented in terms of memmove if all involved types satisfy certain requirements, otherwise it performs assignments - with some classes you can break certain invariants if you bypass their public interface and just go and move / copy them around in memory (for example, I suppose any class with a non-trivial copy constructor is going to misbehave if you make copies of it with memcpy).

Type-safe alternative to C I/O routines are iostreams (and if you want the benefits of the format string, boost::format).

UncleBens
+1  A: 

"Type safety" is using a "type system" to ensure that errors are not propagated within programs. For example, without type safety, it might be possible to (silently) add a string type to floating point type in some undesirable way.

In the instances you're talking about, memcpy() and printf(), the lack of type safety is due to the how the functions treat their arguments. For example, with memcpy(arg1, arg2, len), the len bytes starting at memory address arg2 will be copied to memory address arg1, regardless of how many bytes arg1 points to, potentially overwriting other portions of your program.

For type safe alternatives, look into constructors and cout.

In fact, look into the entire C++ FAQ Lite

Liz Albin
+1  A: 

It means that the compiler will generate no warning if you try to use a type in a way that doesn't make sense for that type. For example, the following is undefined behavior and in practice will copy the bits of a pointer into the bits of a float, where they make absolutely no sense. If sizeof(char*) > sizeof(float), it will overwrite whatever memory locations happen to be just above where f lives.

float f;
char *c = someString();
memcpy(&f, &c, sizeof(char*));
dsimcha
Actually it's undefined behavior for a lot of reasons: use of uninitialised value `c`; might generate a trap representation in f, which would be U.B if used later; might overrun buffer as you identified.
Steve Jessop
@Steve Jessop: The uninitialized value c was a mistake, not intentional. I've fixed it because it was distracting to the real point. Thanks for pointing it out.
dsimcha
A: 

Type safety refers to a coding paradigm that enforces every variable to have a dedicated type at compilation time, for example int a = 4; double d = 100.0; struct ms {char s;} mystruct; The type of a variable is never 'lost'. If you want to change its type from a to b, an explicit or implicit conversion must be defined.

printf is not typesafe because you pass the arguments in a variadic argument list:

float f = 1.f;
printf("This is a float: %f\nAnd this is a string: %s",f,f);

printf does not know which kind of values she receives. The format string is used by the implementation to find out, but if the string is wrong, the implementation has no chance to find it out because there is no type information available at compile-time. The above printf call is most likely to end up catastrophic - printf expects a string as second parameter, but gets a floating-point number.

Alexander Gessler
A: 

A short version of the answer:

class Person;

person.DoSomething(); // This is type safe.

void * p = &person; // You can now start doing unsafe things with p.

You can't pass a Person to memcpy. It only knows and cares about memory. Bytes.

Daniel Daranas
You can pass a (pointer to a) Person to memcpy if Person is a POD class. I think what's more relevant to the issue of type-safety, is that you can't (for example) memcpy a Person to a destination that's not big enough. std::copy, which is type safe, requires that the destination type be assignable from the source type, which memcpy doesn't.
Steve Jessop
@Steve Jessop: `std::copy` doesn't do any range-checking either (the destination buffer may be too small). IMO, the biggest issue with memcpy is that you treat a class as merely a collection of bytes (through the cast to `void*`), thus bypassing the copy constructor. Try copying a `std::string` with memcpy (run in debugger if it otherwise appears to work). - It would be complete impossible to use memcpy in template code, without somehow making sure you are only going to use it with POD types.
UncleBens
+1  A: 

Type safety means that the compiler will help check that you don't mix (incompatible) data types.

For instance, when you call memcpy, the function (and compiler) only sees two pointers in memory, and will happily start copying data. This means you can mix incompatible data types like this:

SomeClass a;
AnotherClass b;
memcpy((void*)&a, (void*)&b, sizeof(b));

There are many approaches to gaining type safety. You could use templates and make a wrapper around mempcy(), ensuring that the two pointers point to the same data type, or you could use other ways.

Since you are already using vectors from the STL, you are already using a more or less type safe implementation.

csl
A: 

The signature of memcpy function is

void *memcpy (void* destination, const void* source, size_t num);

so as you can see it doesn't assume anything about pointers involved with the copy, they are just pointers. So if for example you want to copy a range of ints to a range of floats compiler won't complain about that.

Type Safety is a tool that helps developers to avoid certain errors by preventing some kind of erroneous code being compiled (and lately executed). It analyzes semantic aspect of source code to check if conversion between types and types in general are cohoerent.

What does that mean? It means that if your program passes the type checking phase you can be sure not to generate CERTAIN KIND of errors at run-time.

Of course sometimes you need to force this check not to be done, that's why you can use casts to force things to be what you want. Think about another example, malloc: it is defined to be

void* malloc (size_t size);

so when you want to allocate a pointer to floats for example you do:

float* ptr = (float*)malloc(sizeof(float*)*COUNT);

You are forced to cast the result of the function to be float* otherwise the typecheck will find an assign of a void* to a float* but void* is too generic to be assigned so: TYPE CHECK FAIL!

That's why memcpy is not type-safe. It doesn't check anything, it just copy from a pointer to another pointer.

Jack
A: 

Type safety governs the usage of the compiler checking if the variable is of a right type. C is very loose on data type safety, for example, this is actually in the ANSI C standards, that states that type promotion will occur for data type char, an example in this assignment will explain this,

char ch = 32; /* that is a space character accordingly to ASCII */
int n = ch + 3;

Notice how the ch variable gets 'promoted' to type int. That is legitimate but warrants closer inspection if that is what you are implying.

Compilers such as the C# compiler will not allow this to happen, that is the very reason why in C, there is a usage of cast's operator for example:

int n = (int)3.1456748393f;

Nit picky aside, that is a pi value, (the digits after the decimal point is made up after the 14), what happens, is that the value of n will be 3.

The above serves to illustrate the type safety and that C is very loose on this regard.

Type safety in modern languages is more strict, such as Java, C#, in order to constrain the usage and meaning of the variables. PHP is an excellent example of loose typing, where you could do this:

$myvar = 34;
$myvar = $myvar + "foo";

is $myvar an integer, or is it a floating point or is it a string. The type safety here is not very clear on what is the intention which can lead to bugs and a happy debugging session trying to figure out what is happening.

Hope this helps, Best regards, Tom.

tommieb75