473,387 Members | 2,436 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Strange fwrite

SW1
I wrote a small program which does something like tftp - transfering
files and some chat, anyway i got a problem with fwrite, here is a
snippet of my code:

while(length > 0) {
putchar('.'); //These were for error checking
if(length <= bsize) { //Buffer is bigger than remaining File
realloc(buffer,length * sizeof(char)); //resize buffer
to remain
rec = recv(sock,buffer,length,0); //recieve Data
p = buffer; //set p to buffer
i = length; //set i to remain
while(i > 128) { //break down into 128byte blocks
putchar('.');
fwrite(p,sizeof(char),128,writefile);
p = p + 128; //go to next 128 bytes
i = i - 128;
}
fwrite(p,sizeof(char),i,writefile);
} else {
rec = recv(sock,buffer,bsize,0); //bsize is 1024
putchar('.');
p = buffer;
for(i=0;i<8;i++) {
fwrite(p,sizeof(char),128,writefile);
putchar('.');
p = p + 128;
}
}

length is the length of the whole file to be transmitted, bsize is the
size of the recieve buffer, sock is a socket, p is as pointer, rec and
i are integers.

And now comes my Problem i compiled this code and ran it under Windows
2000 (being the reciever) and it hangs at the fwrite calls (since I
see 2 dots) then i copied the programm to my WinXP machine and it ran
happily!!!

Has Anybody got any Idea whats wrong there??? I costed me 6 hours till
i figured out that it wasn't my fault (after that i tried it on winXP)

One thing to add is whats up with that strange breaking down into 128
Blocks. I ran a small test programm ever increasing the number of
bytes written at once with fwrite, and i got an Error around 140 so i
thought 128 bytes at once should be save.

Thank you soo much.
Nov 13 '05 #1
17 6089

"SW1" <sc**********@yahoo.de> wrote in message
news:79**************************@posting.google.c om...
I wrote a small program which does something like tftp - transfering
files and some chat, anyway i got a problem with fwrite, here is a
snippet of my code:

while(length > 0) {
putchar('.'); //These were for error checking
if(length <= bsize) { //Buffer is bigger than remaining File
realloc(buffer,length * sizeof(char)); //resize buffer
to remain


Where do you store the return of realloc?
Nov 13 '05 #2
SW1
Nowhere, but it does it alright, the only problem i have is with
fwrite!!! fwrite doesn't work even if i don't realloc!!
Nov 13 '05 #3

"SW1" <sc**********@yahoo.de> wrote in message
news:79**************************@posting.google.c om...
Nowhere, but it does it alright, the only problem i have is with
fwrite!!! fwrite doesn't work even if i don't realloc!!


NO!

FIX ALL YOUR PROBLEMS FIRST BEFORE DEBUGING!

LEARN TO F'ING CODE!

GO HOME!
Nov 13 '05 #4
SW1 wrote:
I wrote a small program which does something like tftp - transfering
files and some chat, anyway i got a problem with fwrite, here is a
snippet of my code:

while(length > 0) {
putchar('.'); //These were for error checking
if(length <= bsize) { //Buffer is bigger than remaining File
The // comment syntax was introduced in C99. A C90 compiler is obliged to
issue a diagnostic for a // comment (except in one very odd circumstance in
which it is not a comment at all).
realloc(buffer,length * sizeof(char)); //resize buffer
to remain
....and this is another problem with // comments when used in Usenet
articles.

Now, sizeof(char) is 1 by definition, so you can lose that.

realloc can fail, so catch the return value:

tmp = realloc(buffer, length);
if(tmp != NULL)
{
/* the allocation succeeded */
buffer = tmp;
}
else
{
handle the error in a way appropriate to your program
}

Your failure to handle a realloc failure may be the cause of your problem.
rec = recv(sock,buffer,length,0); //recieve Data


There is no recv function in C.

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 13 '05 #5
"Tom St Denis" <to********@iahu.ca> wrote in message news:<3g*******************@news01.bloor.is.net.ca ble.rogers.com>...
NO!
FIX ALL YOUR PROBLEMS FIRST BEFORE DEBUGING!
LEARN TO F'ING CODE!
GO HOME!


What the illiterate, unhelpful, angsty Tom is trying to convey, is:

realloc(buffer,length * sizeof(char));

This is an unsafe operation. The libc memory manager may move the
location of the block of memory if it can't grow any larger in it's
current location. That means that after a return from realloc,
'*buffer' may no longer point to the actual buffer. Here is an
improvement:

buffer = realloc(buffer, length * sizeof(char));

Now at least, we track the buffer move. The realloc interface is the
most evil in the C library. If realloc fails, then it will not touch
the present buffer but will return NULL (thus causing a memory leak).
So we have to catch this too:

tmp_buffer = realloc(buffer, length * sizeof(char));

if (tmp_buffer == NULL)
fail();

buffer = tmp_buffer;

As you can see, this is very messy, and doing this for each realloc
can be a bit of a pain. You might want to define a cleaner interface
to your memory management functions like so:
int m_alloc(void **pptr, size_t size) {
void *ptr = malloc(size);
if (ptr)
{
*pptr = ptr;
return 0;
}

return 1;
}
int m_realloc(void **pptr, size_t size) {
void *ptr;

/* These magic values change realloc behaviour. */
assert(size > 0);
assert(*pptr != NULL);

ptr = realloc(*pptr, size);

if (ptr)
{
*pptr = ptr;
return 0;
}

return 1;
}
int m_free(void **pptr) {
void *ptr = *pptr;

assert(ptr != NULL);
free(ptr);

*ptr = NULL;
return 0;
}
These functions all return zero on success, or non-zero on error. The
last function will abort your program rather than return error. Now
you can do:

if (m_realloc(&buffer, length * sizeof(char)))
/* handle error. */;

Footnotes:

"*ptr = NULL" in m_free is controversial. As is the NULL itself. A
magic value instead of NULL aids in tracking problems in debugger.

I hacked the m_* functions up in a couple of minutes in Google
Group's posting page. The code is not tested. :)

For a better version of the m_* functions, get a copy of "Writing
Solid Code", Microsoft Press. ISBN: 1-55615-551-4.
David.
Nov 13 '05 #6
David M. Wilson wrote:

<lots of good realloc stuff snipped>
As you can see, this is very messy, and doing this for each realloc
can be a bit of a pain. You might want to define a cleaner interface
to your memory management functions like so:
int m_alloc(void **pptr, size_t size) {
void *ptr = malloc(size);
if (ptr)
{
*pptr = ptr;
return 0;
}

return 1;
}
Alas, whilst void * is a "generic" pointer, void ** isn't. Thus, your code
can be called in a robust manner only by using a void * as a temp:

void *p = myptr;
if(m_alloc(&p, sizeof *myptr))
{
myptr = p;
}
else
{
handle the error.
}

<other functions with same problem snipped>
These functions all return zero on success, or non-zero on error. The
last function will abort your program rather than return error. Now
you can do:

if (m_realloc(&buffer, length * sizeof(char)))
/* handle error. */;
Nope. Sorry, but there it is.
For a better version of the m_* functions, get a copy of "Writing
Solid Code", Microsoft Press. ISBN: 1-55615-551-4.


I'm afraid they suffer from the same problem.

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 13 '05 #7
Richard Heathfield <do******@address.co.uk.invalid> wrote...
int m_alloc(void **pptr, size_t size) {
*pptr = ptr;
}
Alas, whilst void * is a "generic" pointer, void ** isn't. Thus, your code
can be called in a robust manner only by using a void * as a temp:

For a better version of the m_* functions, get a copy of "Writing
Solid Code", Microsoft Press. ISBN: 1-55615-551-4.


Gah, I tried compiling this code and see what you mean. I knew void
pointer dereference didn't make sense. Looking at the Microsoft
example, I see that they first cast the pointer to a 'byte **' (is
'byte' a Microsoftism?). In any case, yuck.

This has got me thinking about a compact, portable, sane memory
interface. And: I've come up blank. With the exception of using gcc's
({ ... }) syntax (eek!), I can't find a nice combination of
functions/macros that allow the syntax I/Steve Maguire[0] initially
suggested. The two ideas I have come up with either depend on compiler
extensions (ugly, bad, and wrong extensions at that), or assume too
much about the size of the pointers they are manipulating.

I've tried to find all sorts of ways around the problem, but have come
up blank so far. For the return value, the best solution I can think
of is something like:

int global_result;
void *op; /* old_ptr */

/* m__a == m__alloc internal function */

#define m_alloc(p, s) \
({ op = p; \
p = m__a_that_sets_g_r(p, s); \
if (! p) p = op; \
global_result; \
})

or

#define m_alloc(p, s) \
({ int r; s = m__a_takes_intp(p, s, &r); r })
The 'global_result' one can't be used for threading, and both are bad
for the eye-sight. :)

Is the only solution to this to cast 'void **' to 'char **' in the
functions? And am I right in saying that this is evil? I'm sure
there's stuff about archs that have different pointer sizes in both
C90 and C99.
David.
(Presently lost in a forest of ugly anti-concepts)

[0] Author of Writing Solid Code.
Nov 13 '05 #8
David M. Wilson wrote:

<snip>
Is the only solution to this to cast 'void **' to 'char **' in the
functions?


No. Been there, tried that, got the tee-shirt very muddy in the process.

The only solution to this is to put up with realloc for general usage, and
write custom reallocation routines for particular types where it makes
sense so to do.

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 13 '05 #9
David M. Wilson wrote:

(snip)

What the illiterate, unhelpful, angsty Tom is trying to convey, is:

realloc(buffer,length * sizeof(char));

This is an unsafe operation. The libc memory manager may move the
location of the block of memory if it can't grow any larger in it's
current location. That means that after a return from realloc,
'*buffer' may no longer point to the actual buffer. Here is an
improvement:

buffer = realloc(buffer, length * sizeof(char));


I believe it is allowed to move it even if the new size is smaller or
equal to the original size.

-- glen

Nov 13 '05 #10

"David M. Wilson" <dw***********@botanicus.net> wrote in message
news:99**************************@posting.google.c om...
"Tom St Denis" <to********@iahu.ca> wrote in message news:<3g*******************@news01.bloor.is.net.ca ble.rogers.com>...
NO!
FIX ALL YOUR PROBLEMS FIRST BEFORE DEBUGING!
LEARN TO F'ING CODE!
GO HOME!


What the illiterate, unhelpful, angsty Tom is trying to convey, is:


I pointed out a line that was wrong. Why should I spend the time to give
the dude working code?

I *was* hoping he would spend the eight seconds, look up "realloc" in either
a man page or a reference somewhere and figure out what the return of
realloc was.

If the OP can't be bothered todo as so much he can bite my shiny metal ass
for all I care.

Tom
Nov 13 '05 #11
"Tom St Denis" <to********@iahu.ca> wrote in message...
I pointed out a line that was wrong. Why should I spend the time to give
the dude working code?
You did it in a manner that was less than polite, and I am not
suggesting you give him working code. Just clearly state what problem
you have, rather than angsting it up on the poor lad.

I *was* hoping he would spend the eight seconds, look up "realloc" in either
a man page or a reference somewhere and figure out what the return of
realloc was.
Unfortunately Tom, we're not all as brilliant and quick-thinking as
you. Helping those lesser than you, rather than being a condescending
twat, helps everyone just that little bit. Maybe some day the favour
will be returned to you.

If the OP can't be bothered todo as so much he can bite my shiny metal ass
for all I care.


You make the assumption that this fellow has access to the
documentation, has the initiative to read it, and is actually capable
of reading it. Furthermore, you make the assumption that this poor
fellow can read your mind, considering you didn't actually tell him
what the problem was, you just shouted a lot.

For someone who is obviously very experienced, and thus capable of
acting so condescending all the time, it's amazing that you never
happened upon any of the fine FAQs on netiquette that are to be found
dotted around the Internet.

I suggest you read one of them, or maybe in your case, all of them.
Learn them off by heart. If by posting violent replies to people, you
somehow think you are gaining the respect of others, think again.
Actually, it makes you look like an angsty know-it-all teen who hasn't
got laid yet. :)

Kindest regards,
David.
Nov 13 '05 #12

"David M. Wilson" <dw***********@botanicus.net> wrote in message
news:99**************************@posting.google.c om...
"Tom St Denis" <to********@iahu.ca> wrote in message...
I pointed out a line that was wrong. Why should I spend the time to give the dude working code?
You did it in a manner that was less than polite, and I am not
suggesting you give him working code. Just clearly state what problem
you have, rather than angsting it up on the poor lad.


Part of being a good "coder" is being able to find our own bugs. Hell ya
I've been stumped and asked for help but often people just have to point the
line number out for me to find/fix the bug.

The OP should learn todo the same. Otherwise there is no point since
they'll be a lousy developer.
I *was* hoping he would spend the eight seconds, look up "realloc" in either a man page or a reference somewhere and figure out what the return of
realloc was.


Unfortunately Tom, we're not all as brilliant and quick-thinking as
you. Helping those lesser than you, rather than being a condescending
twat, helps everyone just that little bit. Maybe some day the favour
will be returned to you.


It already has many-fold. When I started my LTM I was stumped a few times.
However, when I asked for help I didn't say "send me a fixed copy of the
routine for me". I said "thanks for pointing that out I'll go fix it".

I'm the first to admit that people have done alot for me [e.g. free web
hosting, awesome contacts, stipend to a conference, etc, etc]. I'm also the
first to admit the value of some hard work.

I told the OP that his realloc line had a bug in it. There is no point
debugging the rest until he fixes all the mistakes. I mean if I sent in
some half-ass "2 bugs per line" code and asked why it didn't work I wouldn't
say "ok so there are bugs, why doesn't the program work though!?!?!". I
would fix the bugs and then test it out again.
If the OP can't be bothered todo as so much he can bite my shiny metal ass for all I care.


You make the assumption that this fellow has access to the
documentation, has the initiative to read it, and is actually capable
of reading it. Furthermore, you make the assumption that this poor
fellow can read your mind, considering you didn't actually tell him
what the problem was, you just shouted a lot.


"man realloc"

or

"google realloc"

I'm sorry but expecting people to research on their own shouldn't be this
all demanding task. Fuck when I was in grade school we were expected to
find our material with minimal help from the teachers.
For someone who is obviously very experienced, and thus capable of
acting so condescending all the time, it's amazing that you never
happened upon any of the fine FAQs on netiquette that are to be found
dotted around the Internet.
Netiquette is over-rated.
I suggest you read one of them, or maybe in your case, all of them.
Learn them off by heart. If by posting violent replies to people, you
somehow think you are gaining the respect of others, think again.
Actually, it makes you look like an angsty know-it-all teen who hasn't
got laid yet. :)


Know it all... yeah I know how to use "man". Fuck, pass me the Ph.D cuz I'm
a genius...

Tom
Nov 13 '05 #13
Tom St Denis wrote:
"David M. Wilson" <dw***********@botanicus.net> wrote in message
"Tom St Denis" <to********@iahu.ca> wrote in message
NO!
FIX ALL YOUR PROBLEMS FIRST BEFORE DEBUGING!
LEARN TO F'ING CODE!
GO HOME!


What the illiterate, unhelpful, angsty Tom is trying to convey, is:


I pointed out a line that was wrong. Why should I spend the time
to give the dude working code?

I *was* hoping he would spend the eight seconds, look up "realloc"
in either a man page or a reference somewhere and figure out what
the return of realloc was.

If the OP can't be bothered todo as so much he can bite my shiny
metal ass for all I care.


A few days ago I thought I had seen some sane, fairly mature, and
non-offensive responses quoted from Tom, so I unplonked him.
Mistake, now rectified. He *does* give the Ottawa school system
an undeservedly bad name.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 13 '05 #14
"Tom St Denis" <to********@iahu.ca> wrote in message...
For someone who is obviously very experienced, and thus capable of
acting so condescending all the time, it's amazing that you never
happened upon any of the fine FAQs on netiquette that are to be found
dotted around the Internet.
Netiquette is over-rated.
It clearly is not, as your reputation on this group seems to suggest.
It is synonymous with cooperation which as you can imagine, is of
vital importance when communicating across civil boundaries. What if I
posted this reply in Clingonian? Would you then say that netiquette
was over-rated?

Or how about the headers of this message indicated that it was encoded
in "quoted-base13", some strange proprietary encoding that wasn't open
and agreed across the Internet community as a whole.

Your statement is outlandish and counter to everything the Internet
represents. I think you should retract it with an apology. You and
your kind are of a generation of netizens who are willing to take but
not give, making trollish, rebellious, poorly thought out statements
like that above.

Know it all... yeah I know how to use "man". Fuck, pass me the Ph.D cuz I'm
a genius...


Let's go a bit crazy.. let's assume that the original poster is from
far across the Digital Divide. He/she is a native African whos only
access to the Internet is via Usenet and at that, through an
English/native translator who has limited time to translate texts for
him/her.

In this situation, said person might have to wait half a day to get a
translation of the realloc man page, which first would have to be
posted to Usenet by a fellow kind netizen. Or we could just post the
simple, short description of what the problem is in the first place,
and save all that hassle.

I do take your point that a bad developer can be the result of
dependance on others to find/fix bugs, but that is not your problem.
You hang out on a newsgroup which offers help to those who need it,
and when someone asked for help, you TURNED ON CAPS and went all
ape-shit.

This was my original problem with your posting, not that you didn't
offer a solution, but that your attitude sucked and that you did
nothing to help the original poster, bar teaching him that Usenet is
full of whackos and angst-ridden.

Anyway, enough. This is so far off topic that it hurts me to think
about it. If you can't be a good member of the community then I
suggest you pack your PC back away in the Christmas box it came in,
and return it to Dell. Goodnight..
David.
Nov 13 '05 #15
David M. Wilson wrote:
"Tom St Denis" <to********@iahu.ca> wrote in message...
Netiquette is over-rated.

It clearly is not, as your reputation on this group seems to suggest.
It is synonymous with cooperation which as you can imagine, is of
vital importance when communicating across civil boundaries. What if I
posted this reply in Clingonian? [...]


That would, actually, be astonishingly great. Especially the phrase
"This is so far off topic that it hurts me to think about it", I'd
really love to see that in Klingon, if only for future Usenet bickerings
where I am in need of a clever-looking retreat ! :-)

Best regards,

Sidney

Nov 13 '05 #16
Richard Heathfield wrote:
SW1 wrote:

I wrote a small program which does something like tftp - transfering
files and some chat, anyway i got a problem with fwrite, here is a
snippet of my code:

while(length > 0) {
putchar('.'); //These were for error checking
if(length <= bsize) { //Buffer is bigger than remaining File

The // comment syntax was introduced in C99. A C90 compiler is obliged to
issue a diagnostic for a // comment (except in one very odd circumstance in
which it is not a comment at all).


Is the above a reference to...

int a = 10 //* divide by 2 */2;

?

[snip]
--
Lew Pitcher

Master Codewright and JOAT-in-training
Registered Linux User #112576 (http://counter.li.org/)
Slackware - Because I know what I'm doing.

Nov 13 '05 #17
David M. Wilson wrote:
"Tom St Denis" <to********@iahu.ca> wrote in message...
> For someone who is obviously very experienced, and thus capable of
> acting so condescending all the time, it's amazing that you never
> happened upon any of the fine FAQs on netiquette that are to be found
> dotted around the Internet.
Netiquette is over-rated.


It clearly is not, as your reputation on this group seems to suggest.


And, as his reputation on this group (and elsewhere) seems to suggest, he
doesn't give a stuff what you think about netiquette. I'm not sure of the
best way to deal with such trolls, except that I do know it's necessary to
correct their C errors (although TSD is better at C than some of the trolls
we get here), and perhaps it's also wise to reassure the newbies that
Usenet is not entirely full of such people.
It is synonymous with cooperation which as you can imagine, is of
vital importance when communicating across civil boundaries. What if I
posted this reply in Clingonian? Would you then say that netiquette
was over-rated?


Go for it.

--
Richard Heathfield : bi****@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Nov 13 '05 #18

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Antoine Bloncourt | last post by:
Hello everybody Sorry to bother you but I have a problem writing datas into a file ... I want to make a backup of my MySQL database and put the result into a ..sql file. To do this, I use...
0
by: Leif Wessman | last post by:
I'm using proc_open to write to a perl program. Sometimes (not always) the fwrite function below takes about 10 seconds to complete. Most of the time it takes about 0.001 seconds. I don't know what...
6
by: leonecla | last post by:
Hi everybody, I'm facing a very very strange problem with a very very simple C program... My goal should be to write to a binary file some numbers (integers), each one represented as a sequence...
4
by: welch | last post by:
while taking some rough disk performance measures on windows machines, and snooping with FileMon, i've noticed some odd behavior here's the little nul-writer i'm running: def writeTest(nBlocks,...
3
by: sumit1680 | last post by:
Hi everyone, I am using the below listed code The code is #include<stdio.h> #include<stdlib.h> #include<string.h>
2
by: Richard Hsu | last post by:
// code #include "stdio.h" int status(FILE * f) { printf("ftell:%d, feof:%s\n", ftell(f), feof(f) != 0 ? "true" : "false"); } int case1() { FILE * f = fopen("c:\\blah", "wb+"); int i = 5;
4
by: Nate Murray | last post by:
Hey all, I'm having a strange PHP (4.3.10) problem that seems to have something to do with javascript. This is a bit complex, so hold on to your hats. My issue is that a single function is...
4
by: pmz | last post by:
Dear Group, I'm not sure what is going one with my software, but something really strange. I'm storing in BLOB in MySQL data of an image, which I display like: header("Content-Type:...
12
by: hemant.gaur | last post by:
I have an application which writes huge number of bytes into the binary files which is just some marshalled data. int len = Data.size(); //arrary size for (int i = 0; i < len; ++i)...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.