From: PowerStudent on
Hello,
I know, if you want to return an array from a function, you have to
create it per new[] and after using it you have to delete it with
delete[].

I have the following function from my class scheme:

const char* scheme::upperCaseToLowerCase(const char* name){
const size_t length=strlen(name);
char *result = new char[length];
for(size_t i=0; i<=length; ++i){
result[i]=name[i];
}

const int cValue=32;
int isUpperCaseAlpha;
for(char *cur=result;
cur-result<static_cast<int>(length);
++cur){
isUpperCaseAlpha=*cur-static_cast<int>('A');
if(isUpperCaseAlpha>=0&&isUpperCaseAlpha<=25){
*cur+=cValue;
}
}
return result;
}

it's used to make every UPPERCASE character of the input I get to a
LOWERCASE character.

after using this char array, I want to delete it when the
deconstructor of scheme is called:


scheme::~scheme(void)
{
delete[] name;
}


If I try to run my application, I get a error gong when I reache the
delete[] statement.

my question is ... why?

P.S. I'm using MS VC++ 2009
From: Alf P. Steinbach /Usenet on
* PowerStudent, on 13.08.2010 12:39:
> Hello,
> I know, if you want to return an array from a function, you have to
> create it per new[] and after using it you have to delete it with
> delete[].

Well, you know wrongly, so to speak.

There are many ways to return values from functions.


> I have the following function from my class scheme:
>
> const char* scheme::upperCaseToLowerCase(const char* name){
> const size_t length=strlen(name);
> char *result = new char[length];
> for(size_t i=0; i<=length; ++i){
> result[i]=name[i];
> }

Here your array is one element too short, so you get a buffer overrun.


>
> const int cValue=32;
> int isUpperCaseAlpha;
> for(char *cur=result;
> cur-result<static_cast<int>(length);
> ++cur){
> isUpperCaseAlpha=*cur-static_cast<int>('A');
> if(isUpperCaseAlpha>=0&&isUpperCaseAlpha<=25){
> *cur+=cValue;

Assuming an ASCII compatible encoding this could sort of work for English letters.


> }
> }
> return result;
> }
>
> it's used to make every UPPERCASE character of the input I get to a
> LOWERCASE character.
>
> after using this char array, I want to delete it when the
> deconstructor of scheme is called:
>
>
> scheme::~scheme(void)
> {
> delete[] name;
> }
>
>
> If I try to run my application, I get a error gong when I reache the
> delete[] statement.
>
> my question is ... why?

It may be related to your buffer overrun, which is the only bug I see by
skimming the code you present.

But most likely the bug is in the code that you didn't present.

Most likely it's related to failure to think about copying and such.

But a simple cure, whatever the bug is, is to use std::string instead of
dynamically allocated raw arrays.

You might also consider using the C library's function for lowercase a
character, although calling it correctly is a bit tricky.


Cheers & hth.,

- Alf

--
blog at <url: http://alfps.wordpress.com>
From: Francis Glassborow on
PowerStudent wrote:
> Hello,
> I know, if you want to return an array from a function, you have to
> create it per new[] and after using it you have to delete it with
> delete[].
>
> I have the following function from my class scheme:
>
> const char* scheme::upperCaseToLowerCase(const char* name){
> const size_t length=strlen(name);
> char *result = new char[length];
> for(size_t i=0; i<=length; ++i){
> result[i]=name[i];
> }
>
> const int cValue=32;
> int isUpperCaseAlpha;
> for(char *cur=result;
> cur-result<static_cast<int>(length);
> ++cur){
> isUpperCaseAlpha=*cur-static_cast<int>('A');
> if(isUpperCaseAlpha>=0&&isUpperCaseAlpha<=25){
> *cur+=cValue;
> }
> }
> return result;
> }
>
> it's used to make every UPPERCASE character of the input I get to a
> LOWERCASE character.
>
> after using this char array, I want to delete it when the
> deconstructor of scheme is called:
>
>
> scheme::~scheme(void)
> {
> delete[] name;
> }
>
>
> If I try to run my application, I get a error gong when I reache the
> delete[] statement.
>
> my question is ... why?
>
> P.S. I'm using MS VC++ 2009

Your code looks very confused. Was name a member of scheme? What is the
significance of cValue (it is only useful if the character set is ASCII
but the name gives no hint of this)

Look at the following:

string scheme::convert_to_lower_case(string name){
for(int i=0; i<name.size(); ++i){
name[i] = std::tolower(name[i]);
}
return string;
}

Though it seems to require an extra copy of the string, in practice many
compilers will optimise that away.

It is a good idea to become familiar with the tools provided by the
standard library. Note that my code is independent of the character
coding whilst yours implicitly requires ASCII.

From: Francis Glassborow on
Alf P. Steinbach /Usenet wrote:
> * PowerStudent, on 13.08.2010 12:39:
>> Hello,
>> I know, if you want to return an array from a function, you have to
>> create it per new[] and after using it you have to delete it with
>> delete[].
>
> Well, you know wrongly, so to speak.
>
> There are many ways to return values from functions.
>
>
>> I have the following function from my class scheme:
>>
>> const char* scheme::upperCaseToLowerCase(const char* name){
>> const size_t length=strlen(name);
>> char *result = new char[length];
>> for(size_t i=0; i<=length; ++i){
>> result[i]=name[i];
>> }
>
> Here your array is one element too short, so you get a buffer overrun.

I think not, instead his for loop iterates for one too many times.

>
>
>>
>> const int cValue=32;
>> int isUpperCaseAlpha;
>> for(char *cur=result;
>> cur-result<static_cast<int>(length);
>> ++cur){
>> isUpperCaseAlpha=*cur-static_cast<int>('A');
>> if(isUpperCaseAlpha>=0&&isUpperCaseAlpha<=25){
>> *cur+=cValue;
>
> Assuming an ASCII compatible encoding this could sort of work for
> English letters.

Yes but will fail for other letters and for non-ASCII character encodings

>
>
>> }
>> }
>> return result;
>> }
>>
>> it's used to make every UPPERCASE character of the input I get to a
>> LOWERCASE character.
>>
>> after using this char array, I want to delete it when the
>> deconstructor of scheme is called:
>>
>>
>> scheme::~scheme(void)
>> {
>> delete[] name;
>> }
>>
>>
>> If I try to run my application, I get a error gong when I reache the
>> delete[] statement.
>>
>> my question is ... why?
>
> It may be related to your buffer overrun, which is the only bug I see by
> skimming the code you present.

Well where is name declared? The only use of name in the above is as an
input argument. Unless name is dynamically assigned with an array that
was created with new, and attempt to aplly delete[] to it will fail,
possibly catastrophically.


I suspect that the OP thinks there is some magic link between the input
parameter and the returned value.
From: Francis Glassborow on
Francis Glassborow wrote:
> Alf P. Steinbach /Usenet wrote:
>> * PowerStudent, on 13.08.2010 12:39:
>>> Hello,
>>> I know, if you want to return an array from a function, you have to
>>> create it per new[] and after using it you have to delete it with
>>> delete[].
>>
>> Well, you know wrongly, so to speak.
>>
>> There are many ways to return values from functions.
>>
>>
>>> I have the following function from my class scheme:
>>>
>>> const char* scheme::upperCaseToLowerCase(const char* name){
>>> const size_t length=strlen(name);
>>> char *result = new char[length];
>>> for(size_t i=0; i<=length; ++i){
>>> result[i]=name[i];
>>> }
>>
>> Here your array is one element too short, so you get a buffer overrun.
>
> I think not, instead his for loop iterates for one too many times.

Sorry, you are right he forgot the null terminator (I was thinking in
C++ string context. However he should have made length 1 largerand got
rid of the confusing <= and replaced it with <:

const size_t length=strlen(name) + 1;
char *result = new char[length];
for(size_t i=0; i<length; ++i){
result[i]=name[i];
}