KUDOS!!!!!!!!!!!!! I say that in StackOverflow and had my account banned. ;-)
KUDOS!!!!!!!!!!!!! I say that in StackOverflow and had my account banned. ;-)
I missed the OP, but the thread title seems to me to be in error, because AIUI the whole purpose of the cast facility is to be able to cast a number as an integer pointer for accessing memory=mapped I/O.
Can't get much lower than that!
That is one use for it, far from the only one. It is also very useful in many situations where an OO approach might seem more natural but the efficiency of directly controlling the memory behaviour matters.
-- Steve O'Hara-Smith | Directable Mirror Arrays C:\>WIN | A better way to focus the sun The computer obeys and wins. | licences available see You lose and Bill collects. | http://www.sohara.org/
That was the beauty of C. Years ago I was handed a ghastly hack of TurboPascal that needed to read a ram disk clock, and decide whetheer it was a FAT, File entry, or a data block. Based on the first few bytes it might be almost anything.
It proved quicker to write it in C where the data block could be read as an array of words, then depending on the value of some works, cast into an array of something else or a struccture...
...I spent an entire Sunday rewriting the whole program in C in a hotel room in Orleans...
I love the fact that C will gently ask whether you really meant to treat an integer as a pointer to a string, and assume that oince you explicitly cast it so, you are clever enough to mean it.
Only once has C let me down. In Assembler it is trivial to set up a call table - an arraye of address of subroutines that are called depending on an indexz value in te accumultaor. You take the base address of te aqrray into one regsiter, add the left shifted (on an 8 bit mnicro) accumulator to it and call te address ponted to by that register.
And array of pointers to functions was beyond my ability to specify, and the crude 6809 compiler to understand anyway.
So I wrote it as an 'if then... else if..' chain...
-- Ideas are more powerful than guns. We would not let our enemies have guns, why should we let them have ideas? Josef Stalin
If you want OO *structure* you can use it in pure C by using siource fuiles littered with STATICs and conatining their own data and their won menss of modifying te dayta by function calls.
Operator overloeading? The whole reason I write in C is precisely becaiuse I do not want inadvertent passing of a numercal string to a function expecting an integer to second guess me. It's a MISTAKE, not a feature.
OO langeus are like fixed speed linmits. Ok for numpties but a pain in te ass for peoole who know how to drive in all conditions.
And then we hasve 'code generators' because no one can program in them anyway...
-- "And if the blind lead the blind, both shall fall into the ditch". Gospel of St. Mathew 15:14
More a demonstration of a lack of experience with turbo pascal than anything else. It will go low down and dirty if you want and give you raw memory access, untyped pointers etc.
You mean like having an array of function pointers in C, and calling the one at a certain index?
You can get lame compilers for pretty much any language IME!
No "switch" statement?
-- Cheers, John. /=================================================================\ | Internode Ltd - http://www.internode.co.uk | |-----------------------------------------------------------------| | John Rumm - john(at)internode(dot)co(dot)uk | \=================================================================/
Never found out how to in the four hours I spent reading the manual
There was, but on a 6809 the code was simply horrible.
I only had IIRC three possibles. so if then else if then else
was pretty compact.
>-- To ban Christmas, simply give turkeys the vote.
(too many newsgroups, had to snip a few)
Richard,
:-) And thats exactly the kind of thing you should try to avoid.
In this simple example it will work, but you're /still/ trying to write a full buffers worth - when you should leave that last character untouched, just in case.
Ofcourse, I would rather check the length of the to-be-copied string and throw an error when it doesn't fit, but maybe thats just me ... (Just imagine you're copying some kind of commandline string, with a few argument switches at the end).
Regards, Rudy Wieser
That is an option if you know roughly what SHOULD be there.
-- "The most difficult subjects can be explained to the most slow witted man if he has not formed any idea of them already; but the simplest thing cannot be made clear to the most intelligent man if he is firmly persuaded that he knows already, without a shadow of doubt, what is laid before him." - Leo Tolstoy
(Sorry, didn't notice. But you left comp.programming in, so we're good.)
That last character is the null terminator. Given the choice, that's how I like my strings to end. :-)
Okay, so that's so obvious a retort that I have to deduce you meant something else, but I don't know what. Care to explain for the benefit of my befuddled grey cells?
Reporting an error is certainly preferable to undefined behaviour, but I would prefer to grab the data - all of it - if that's possible and reasonable.
(There may be times when it's *not* reasonable to try to grab all the data - for example, if someone is deliberately throwing complete-Shakespeare-in-one-line at you over and over again in an attempt to make you consume the whole of memory. So of course you have to do your threat assessment: is the program going to be used in a context where this sort of thing is likely? If so, you need some rules for how much data is to be considered acceptable.)
-- Richard Heathfield Email: rjh at cpax dot org dot uk "Usenet is a strange place" - dmr 29 July 1999 Sig line 4 vacant - apply within
Richard,
You responded to a post in which was explained that "strncpy" could be dangerous because you could fill the buffer out with a too-long string, leaving it without a terminator. The defensive method would be to stop copying before you overwrite the last byte in the target buffer - thereby making sure that whatever may happen, the buffer will hold a zero-terminated string.
I went along with you upto-and-including the "- all of it -". The latter part ? Not so much. Not even humans are really capable of acting (correctly!) on partial messages, let alone un-imaginative programs. And boy, can they do a lot of damage ...
Regards, Rudy Wieser
TNP,
You got that backwards I'm afraid: the usage of "strncpy" in a "disregard whatever you can't copy" way is only a good(ish) idea when you /know/ that what you dropped is of no consequence.
In all other circumstances letting a program (or human!) act on partial data will be a hommage to the old "garbage in, garbage out" saying. :-)
Regards, Rudy Wieser
With you so far...
But my code protected against that possibility by obtaining the length of the source string including terminator: len = strlen(src) + 1; and then allocating exactly that amount of memory via malloc, and then using memcpy to copy exactly that many bytes. The only way this could break would be if the source string grew between two consecutive lines of code that did not grow that string. This *could* happen in a multi-threaded context, of course, but in a multi-threaded context one would take additional precautions to ensure that only one thread had access to the string at the point of duplication.
OR... I'm missing something! :-)
Well, if it's impossible it's impossible and that's all there is to it. And I gave an example of a scenario in which an unreasonable amount of data could be deliberately thrown at the program with the express intent of consuming all available memory. If these circumstances are at all likely, it seems to me that it is better to protect against them than to succumb blindly to them.
-- Richard Heathfield Email: rjh at cpax dot org dot uk "Usenet is a strange place" - dmr 29 July 1999 Sig line 4 vacant - apply within
Richard,
Thats why I said "In this simple example it will work".
In your example ? Yes (and the same as I was thinking).
Now imagine that you're programming and you /could/ be working on a single-thread string, but as easily on a multi-thread one. Wouldn't it be easier to use a method which will work in either circumstance ?
True. But that only goes as far as the programmer can imagine such attacks. "strncpy" is ment as a "last ditch" effort to safeguard against the /unforseen/ circumstances which could lead to memory/stack being clobbered. My suggestion to provide it an argument that is one less than what the buffer can actually hold is just an extension on that.
Personally I would not mind at all when it would throw or return an error when the target buffer was found to be too small for the source string. It should never happen, and for that reason should not be silently ignored either. But thats just my take on it, YMMV.
Regards, Rudy Wieser
I will grant that some programmers might be in that position, but I'm not one of them.
It has rightly been said that threading is for people who don't understand state machines, and state machines are for people who don't understand threading. I am in the latter camp!
In the more general case, however, your point is taken.
-- Richard Heathfield Email: rjh at cpax dot org dot uk "Usenet is a strange place" - dmr 29 July 1999 Sig line 4 vacant - apply within
"Just in case" what, exactly? Are you trying to guard against an off-by-one error but not worry about an off-by-two error?
-- Keith Thompson (The_Other_Keith) kst-u@mib.org Will write code for food. void Void(void) { Void(); } /* The recursive call of the void */
Assuming you bzeroed the target block before copying first. strncpy does npot zero terminate te target block
Well sometimes one can say 'sorry buffer overflowed: can you resend that last bit"
Case where its nopt reasonable to garb all et data? well mail programs. I blacklist anything endi in .tv, .info, .biz and dozens of other top level domains that are entirely owned by spam marketing companies.
I only grab enough data to establish that before sending them packing
-- You can get much farther with a kind word and a gun than you can with a kind word alone. Al Capone
Hey, I understand both!
And have written code to implement both!
Sometimes in the same program! That was the program that also uses longjmp()
30 subroutrines deep you are reading characters from a telex line, and the line drops...exit up through 30 subs? nah. set an error code LINE_DROP and longjmp back to an exit point, look at the error code and clean up the hardware and print what of the telex you did get...I remember sitting with a telex directory deliberatrely tring to contact companies in equatorial africa to send them test telexes on the basis that they were usually only capable of sustaining a connection till the mext lightning strike.
No idea who they were.
-- Socialism is the philosophy of failure, the creed of ignorance and the gospel of envy. Its inherent virtue is the equal sharing of misery. Winston Churchill
"R.Wieser" writes: [...]
No, strncpy is designed to work with a specific (and, in recent history, rare) data structure, namely a fixed-length character array containing some bytes of meaningful data padded to the end by zero or more null bytes. (I believe it was used to store file names in Unix directory entries.)
(followups to comp.lang.c only)
-- Keith Thompson (The_Other_Keith) kst-u@mib.org Will write code for food. void Void(void) { Void(); } /* The recursive call of the void */
Yeah the manuals and built in help improved massively with later versions, but were a bit sparse for the early versions.
There was s significant improvement with V4 IIRC (although the footprint of the development system got *much* larger as well - V3 always amazed me in that it included editor, compiler, linker, run time system etc all in a single 50K executable!).
The neatest way to do that in TP was usually to create a "Packed"[1] Variant Record data structure (like a union in C), with whatever fields you want, and then have variants that treat the data in other ways - something like a straight array of bytes. E.g:
var buffer [0..BuffSize] of byte ;
(or if you want it true C style just make the array a single byte long and then index off the end of it - the compiler did not range check unless you explicitly told it to)
[1] Using a packed record stopped the compiler padding the structure for efficiency - say moving byte wide fields onto word boundaries)Then when you create in instance of that record, you could map it to an absolute memory location using the "absolute" keyword and specifying the address.
There was also a predefined array called mem that simply mapped to memory.
Yup gets the job done, and in code terms is not usually going to be any worse that a switch.
-- Cheers, John. /=================================================================\ | Internode Ltd - http://www.internode.co.uk | |-----------------------------------------------------------------| | John Rumm - john(at)internode(dot)co(dot)uk | \=================================================================/
ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.