Vik
Vik

Reputation: 11

Runtime crash while using _tcsset

1. I wrote the following code which compiles but crashes at run-time showing "Access violation writing" while calling _tcsset .

void function(TCHAR *tsatz)
{
    printf( "Before: %s\n", tsatz );
    _tcsset(tsatz,'*');
    printf( "After: %s\n", tsatz );
}

void main( void )
{
    TCHAR* tsatz;
    tsatz = new char[256];
    tsatz = "This is a test string ";
    function(tsatz);
    getchar();
}

Where am I wrong while using _tcsset ?

2. I know all the "safe" functions work if we tell them how big the target buffer is. But if i need to use _tcsset_s in "function" where tsatz is coming from external, is there a way?

I am a beginner. Any help i could get is greatly appreciated. Thanks in advance.

Upvotes: 1

Views: 116

Answers (2)

paulsm4
paulsm4

Reputation: 121799

The problem with your code is that you assign a read-only C string to the pointer variable TCHAR* tsatz;; hence the access violation.

POSSIBLE SOLUTION:

TCHAR tsatz[256] = "This is a test string ";
function(tsatz);

"_tcsset()" and friends are non-portable; you're not likely to see them very often even in Windows-only code.

A much better solution, if possible for your application, would be to use C++ "std:string".

For example,

std::string tsatz = "This is a test string ";
std::fill(tsatz.begin(), tsatz.end(), '*');

Upvotes: 0

user657267
user657267

Reputation: 21000

You are modifying a string literal, this is undefined behavior.

tsatz = "This is a test string ";

This will not copy the string literal into tsatz, it simply assigns tsatz to point to the address of "This is a test string ";, which cannot be modified. One way around this is to declare tsatz as an array and initialize it with the string literal, which will automatically copy the text into the array for you

TCHAR tsatz[] = "This is a test string ";

If you need to keep track of the size of an array, you will either need to do so explicitly (note that sizeof an array will only work if the operand actually is an array, and not a pointer):

void function(TCHAR *tsatz, size_t numberOfElements)
{
    _tprintf( "Before: %s\n", tsatz );
    _tcsset_s(tsatz, numberOfElements, '*');
    _tprintf( "After: %s\n", tsatz );
}

void main( void )
{
    TCHAR tsatz[] = "This is a test string ";
    function(tsatz, sizeof tsatz / sizeof(TCHAR));
    getchar();
}

or use a template

template<size_t sz>
void function(TCHAR (tsatz&)[sz])
{
    _tprintf( "Before: %s\n", tsatz );
    _tcsset_s(tsatz, sizeof tsatz / sizeof(TCHAR), '*');
    _tprintf( "After: %s\n", tsatz );
}

Or you could just use std::basic_string instead.

Upvotes: 2

Related Questions