C++ Crashes in a 'For' Loop with a Negative Expression

C++ crashes in a 'for' loop with a negative expression

s.length() is unsigned integer type. When you subtract 3, you make it negative. For an unsigned, it means very big.

A workaround (valid as long the string is long up to INT_MAX) would be to do like this:

#include <string>

using namespace std;

int main() {

string s = "aa";

for (int i = 0; i < static_cast<int> (s.length() ) - 3; i++) {

}
}

Which would never enter the loop.

A very important detail is that you have probably received a warning "comparing signed and unsigned value". The problem is that if you ignore those warnings, you enter the very dangerous field of implicit "integer conversion"(*), which has a defined behaviour, but it is difficult to follow: the best is to never ignore those compiler warnings.


(*) You might also be interested to know about "integer promotion".

For-Loop a Empty Vector with negative iterator?

That's because std::vector::size() returns size_type as type, this type is unsigned. This means that i < myVector.size() compares two different types, int and unsigned int. The compiler will "promote" your int to an unsigned type. Because this int is negative and unsigned types can't hold negative values it will wrap around and you'll end up with a very big value and thus the loop condition is never met.

You could cast size() explicitly:

std::vector<int> myVector;
for (int i = myVector.size() - 10; i < static_cast<int>(myVector.size()); i++) {
std::cout << "Vector Loop: i = " << i << std::endl;
}

Or for a cleaner approach try using rbegin() and loop until rend() or until you've looped 10 times, something like:

std::vector<int> myVector;
//fill vector..
auto itr = myVector.rbegin();
int count = 10;
while(itr != myVector.rend() && count-- > 0)
{
//process.
++itr;
}

program crashes at repetitive calloc() call

element = (Element*)calloc(0, sizeof(Element));

what is 0 in first argument?

actually you ask for 0 number of your type from memory!

here is some explanation about dynamic memory allocation:

Dynamic memory allocation is a process of allocating memory at run time. There are four library routines, calloc(), free(), realloc(), and malloc() which can be used to allocate memory and free it up during the program execution. These routines are defined in the header file called stdlib.h.

What is malloc() ?

It is a function which is used to allocate a block of memory dynamically. It reserves memory space of specified size and returns the null pointer pointing to the memory location.

The pointer returned is usually of type void. It means that we can assign malloc function to any pointer. The full form of malloc is memory allocation.

What is calloc() ?

Calloc() function is used to allocate multiple blocks of memory. It is a dynamic memory allocation function which is used to allocate the memory to complex data structures such as arrays and structures. If this function fails to allocate enough space as specified, it returns will null pointer. The full form of calloc function is contiguous allocation.

Why use malloc() ?

Here are the reasons of using malloc()

You should use malloc() when you have to allocate memory at runtime.
You should use malloc when you have to allocate objects which must exist beyond the execution of the current memory block.
Go for malloc() if you need to allocate memory greater than the size of that stack.
It returns the pointer to the first byte of allocated space.
It enables developers to allocate memory as it is needed in the exact amount.
This function allocates a memory block size of bytes from the heap.

Why use calloc() ?

Here are the reasons of using calloc()

When you have to set allocated memory to zero.
You can use calloc that returns a pointer to get access to memory heap.
Used when you need to initialize the elements to zero to returns a pointer to the memory.
To prevent overflow that is possible with malloc()
Use calloc() to request a page that is known to already be zeroed.

Syntax of malloc()
Here is a Syntax of malloc()

ptr = (cast_type *) malloc (byte_size);

n above syntax, ptr is a pointer of cast_type. The malloc function returns a pointer to the allocated memory of byte_size.

Example of malloc() in C

In the bellow code, sizeof(*ptr) is used to allocate a memory block of 15 integers. In the printf statement, we are finding the value of the 6th integer.

#include<stdlib.h>
#include<stdio.h>
int main(){
int *ptr;
ptr = malloc(15 * sizeof(*ptr));
if (ptr != NULL) {
*(ptr + 5) = 480;
printf("Value of the 6th integer is %d",*(ptr + 5));
}
}

Output:

Value of the 6th integer is 480

Syntax of calloc()

Here is a Syntax of malloc()

ptr = (cast_type *) calloc (n, size);

The above syntax is used to allocate n memory blocks of the same size. After the memory space is allocated, all the bytes are initialized to zero. The pointer, which is currently at the first byte of the allocated memory space, is returned.

Example of calloc() in C

The C language program below calculates the sum of the first ten terms. If the pointer value if null, then the memory space will not be allocated.
For loop is used to iterate the value of a variable "i" and print the sum. Lastly, function free is used to free-up the pointer.

#include <stdio.h>
#include <stdlib.h>
int main() {
int i, * ptr, sum = 0;
ptr = calloc(10, sizeof(int));
if (ptr == NULL) {
printf("Error! memory not allocated.");
exit(0);
}
printf("Building and calculating the sequence sum of the first 10 terms \n");
for (i = 0; i < 10; ++i) { * (ptr + i) = i;
sum += * (ptr + i);
}
printf("Sum = %d", sum);
free(ptr);
return 0;
}

Output:

Building and calculating the sequence sum of the first 10 terms n Sum = 45

How can I fix my program to not crash if I run any character that is not alphabetical?

i is the do ... while counter, do not use it to count the number of letters, use another variable, something like:

int count_letters(string text)
{
int i = 0, letters = 0;
do
{
if (isalpha((unsigned char)text[i]))
{
letters++;
}
i++;
}
while (text[i] != 0);
return letters;
}

Notice that with your approach the loop is also testing the NUL terminator in an empty string, use a while loop instead to exit the loop as soon as the NUL is found:

int count_letters(string text)
{
int letters = 0;
while (*text)
{
if (isalpha((unsigned char)*text))
{
letters++;
}
text++;
}
return letters;
}

post decrement in while conditon in C

This cycle will end with x equal to -1 (assuming x is signed), but its body will not produce access to array[-1] at the last step. The last array access is to array[0]. The behavior is consistent across all implementations.

In other words, there's no problem with negative index array access in the code you quoted. But if you attempt to access array[x] immediately after the cycle, then you'll indeed access array[-1].

The code you quoted is a variation of a fairly well-known implementational pattern used when one needs to iterate backwards over an array using an unsigned variable as an index. For example

unsigned x;
int a[5];

for (x = 5; x-- > 0; )
a[x] = 0;

Sometimes less-experienced programmers have trouble using unsigned indices when iterating backwards over an array. (Since unsigned variables never have negative values, a naive implementation of the cycle termination condition as x >= 0 does not work.) This approach - i.e. post-increment in the cycle termination condition - is what works in such cases. (Of course, it works with signed indices as well).



Related Topics



Leave a reply



Submit