I'm not very good into coding/programming but I'm trying to compile Linux Source.
Following errormessage shows up:
error: invalid conversion from ‘const char*’ to ‘char*’ [-fpermissive]
char *ptr = strchr( in, ch );
While "googling" around I could't find a helpfull answer.
I guess this is the part where it fails:
//////////////////////////////////////////////////////////////////////////
/// Parses an IP address string
///
/// #param[out] out array containing the IP address in raw 4-byte format
/// #param in string containing an IP address in 'nnn.nnn.nnn.nnn'
/// notation
//////////////////////////////////////////////////////////////////////////
int parseIP( uint8_t *out, const char *in )
{
in_addr addr, haddr;
int c = 0;
int ch = '.';
char *ptr = strchr( in, ch );
while( ptr ) {
++c;
ptr = strchr( ptr + 1, ch );
}
if( c != 3 )
return -EINVAL;
if( inet_aton( in, &addr ) == 0 )
return -EINVAL;
haddr.s_addr = ntohl( addr.s_addr );
for( int i = 0; i < 4; ++i )
out[ i ] = ((uint8_t *)&haddr.s_addr)[ 3 - i ];
return 0;
}
Hopefully anyone can help.
Regards,
Mark
Hi David,
I've found the part were it's been called and tried to change it, but still same errormessage while using th 'make' command.
case 'i':
if( getuid() != 0 ) {
std::cerr << "Error: you need to have "
"root privileges in "
"order to use the "
"-i/--ipaddr option"
<< std::endl;
exit( 1 );
}
if( strncmp( optarg, "dhcp", 4 ) == 0 &&
strlen( optarg ) == 4 )
opt_devip_dhcp = 1;
else if( parseIP( opt_devip, (char *)optarg ) ) {
std::cerr << "Error: bad IP address" <<
std::endl;
exit( 3 );
}
opt_devip_set = 1;
break;
case 'm':
if( parseIP( opt_devmask, (char *)optarg ) ) {
std::cerr << "Error: bad network mask" <<
std::endl;
exit( 7 );
}
opt_devmask_set = 1;
break;
int parseIP( uint8_t *out, const char *in )
You need to find where parseIP is called in your main program. See above how the second argument is const char *in. You summize correctly that is probably where the error is generated. If you check in your main program where parseIP is called, you will probably find your program passing it a char * argument instead of const char *. You can correct this in the code by casting the value passed to parseIP to (char *) Example: if you find this:
somevar = parseIP( outvar, stringin )
Cast the second argument to (char *):
somevar = parseIP( outvar, (char *)stringin )
Or you can probably just cheat with the compiler. It is giving you a hint on how to do it. Notice the [-fpermissive] as part of the warning. You can more than likely just pass the -fpermissive flag to the compiler and have it work. If you were compiling with:
gcc -Wall -o outfile yourfile.cpp
Try it with:
gcc -Wall -o outfile yourfile.cpp -fpermissive
Now, all the legal qualifications and disclaimers apply, you are better fixing the reason you are getting that warning/error as set forth above, but you can also just pass -fpermissive as a temporary workaround most of the time.
Related
I use spike to run the test program in "riscv-tools/riscv-tests/build/benchmarks":
$ spike multiply.riscv
And the output shows:
mcycle = 24096
minstret = 24103
Why mcycle is less than minstret?
Dose it means that spike can run more than one instructions in one cycle?
(I tried to trace spike code but cannot find how mcycle is counted.)
The printing of mcycle and minstret values are not from Spike in this case, it is from the test (benchmark). There is the code:
https://github.com/ucb-bar/riscv-benchmarks/blob/master/common/syscalls.c
#define NUM_COUNTERS 2
static uintptr_t counters[NUM_COUNTERS];
static char* counter_names[NUM_COUNTERS];
static int handle_stats(int enable)
{
int i = 0;
#define READ_CTR(name) do { \
while (i >= NUM_COUNTERS) ; \
uintptr_t csr = read_csr(name); \
if (!enable) { csr -= counters[i]; counter_names[i] = #name; } \
counters[i++] = csr; \
} while (0)
READ_CTR(mcycle);
READ_CTR(minstret);
#undef READ_CTR
return 0;
}
There is some code between reading mcycle & minstret. And now you know how much code is there between readings.
In Spike mcycle & minstret are always equal by definition (they are handled by the same code): https://github.com/riscv/riscv-isa-sim/blob/9e012462f53113dc9ed00d7fbb89aeafeb9b89e9/riscv/processor.cc#L347
case CSR_MINSTRET:
case CSR_MCYCLE:
if (xlen == 32)
state.minstret = (state.minstret >> 32 << 32) | (val & 0xffffffffU);
else
state.minstret = val;
break;
The syscalls.c was linked into multiply.riscv binary from https://github.com/ucb-bar/riscv-benchmarks/blob/master/multiply/bmark.mk - multiply_riscv_bin = multiply.riscv
$(multiply_riscv_bin): ... $(patsubst %.c, %.o, ... syscalls.c ... )
There is _init in syscalls.c function which calls main of the test and prints values, recorded on SYS_stats "syscall" with handle_stats.
void _init(int cid, int nc)
{
init_tls();
thread_entry(cid, nc);
// only single-threaded programs should ever get here.
int ret = main(0, 0);
char buf[NUM_COUNTERS * 32] __attribute__((aligned(64)));
char* pbuf = buf;
for (int i = 0; i < NUM_COUNTERS; i++)
if (counters[i])
pbuf += sprintf(pbuf, "%s = %d\n", counter_names[i], counters[i]);
if (pbuf != buf)
printstr(buf);
exit(ret);
}
My doubts are as follows :
1 : how to send 'str' from function 'fun' , So that i can display it in main function.
2 : And is the return type correct in the code ?
2 : the current code is displaying some different output.
char * fun(int *arr)
{
char *str[5];
int i;
for(i=0;i<5;i++)
{
char c[sizeof(int)] ;
sprintf(c,"%d",arr[i]);
str[i] = malloc(sizeof(c));
strcpy(str[i],c);
}
return str;
}
int main()
{
int arr[] = {2,1,3,4,5},i;
char *str = fun(arr);
for(i=0;i<5;i++)
{
printf("%c",str[i]);
}
return 0;
}
how to send 'str' from function 'fun' , So that i can display it in main function.
This is the way:
char* str = malloc( size );
if( str == NULL ) {
fprintf( stderr,"Failed to malloc\n");
}
/* Do stuff with str, use str[index],
* remember to free it in main*/
free(str);
And is the return type correct in the code ?
No, Probably char** is the one you need to return.
the current code is displaying some different output.
Consider explaining what/why do you want to do ? The way you have written, seems completely messed up way to me. You're passing array of integer but not its length. How is the fun() supposed to know length of array? Another problem is array of pointers in fun().
You can't write a int to a char (See the both size). So I used char array instead.
However, I'm not sure if this is what you want to do (might be a quick and dirty way of doing it):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char**
fun(int *arr, int size)
{
char **str = malloc( sizeof(char*)*size );
if( str == NULL ) {
fprintf( stderr, "Failed malloc\n");
}
int i;
for(i=0;i<5;i++) {
str[i] = malloc(sizeof(int));
if( str == NULL ) {
fprintf( stderr, "Failed malloc\n");
}
sprintf(str[i],"%d",arr[i]);
}
return str;
}
int
main()
{
int arr[] = {2,1,3,4,5},i;
char **str = fun(arr, 5);
for(i=0;i<5;i++) {
printf("%s\n",str[i]);
free(str[i]);
}
free(str);
return 0;
}
I made these changes to your code to get it working:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **fun(int *arr)
{
char **str = malloc(sizeof(char *) * 5);
int i;
for(i = 0; i < 5; i++) {
if ((arr[i] >= 0) && (arr[i] <= 9)) {
char c[2] ;
sprintf(c, "%d", arr[i]);
str[i] = (char *) malloc(strlen(c) + 1);
strcpy(str[i],c);
}
}
return str;
}
int main()
{
int arr[] = {2, 1, 3, 4, 5}, i;
char **str = fun(arr);
for(i = 0; i < 5; i++) {
printf("%s", str[i]);
free(str[i]);
}
printf("\n");
free(str);
return 0;
}
Output
21345
I added a check to make sure that arr[i] is a single digit number. Also, returning a pointer to a stack variable will result in undefined behavior, so I changed the code to allocate an array of strings. I don't check the return value of the malloc calls, which means this program could crash due to a NULL pointer reference.
This solution differs from the others in that it attempts to answer your question based on the intended use.
how to send 'str' from function 'fun' , So that i can display it in main function.
First, you need to define a function that returns a pointer to array.
char (*fun(int arr[]))[]
Allocating variable length strings doesn't buy you anything. The longest string you'll need for 64bit unsigned int is 20 digits. All you need is to allocate an array of 5 elements of 2 characters long each. You may adjust the length to suit your need. This sample assumes 1 digit and 1 null character. Note the allocation is done only once. You may choose to use the length of 21 (20 digits and 1 null).
For readability on which values here are related to the number of digits including the terminator, I'll define a macro that you can modify to suit your needs.
#define NUM_OF_DIGITS 3
You can then use this macro in the whole code.
char (*str)[NUM_OF_DIGITS] = malloc(5 * NUM_OF_DIGITS);
Finally the receiving variable in main() can be declared and assigned the returned array.
char (*str)[NUM_OF_DIGITS] = fun(arr);
Your complete code should look like this:
Code
char (*fun(int arr[]))[]
{
char (*str)[NUM_OF_DIGITS] = malloc(5 * NUM_OF_DIGITS);
int i;
for(i=0;i<5;i++)
{
snprintf(str[i],NUM_OF_DIGITS,"%d",arr[i]); //control and limit to single digit + null
}
return str;
}
int main()
{
int arr[] = {24,1,33,4,5},i;
char (*str)[NUM_OF_DIGITS] = fun(arr);
for(i=0;i<5;i++)
{
printf("%s",str[i]);
}
free(str);
return 0;
}
Output
2413345
With this method you only need to free the allocated memory once.
how do i avoid using pointer variables and pointer-based pass-by-reference in this program? as my instructor said there is no need to use pointers. This is a the tortoise and the hare simulator , you will use number generation to develop a simulation of this memorable event.
#include <iostream>
using std::cout;
using std::endl;
#include <cstdlib>
using std::rand;
using std::srand;
#include <ctime>
using std::time;
#include <iomanip>
using std::setw;
const int RACE_END = 70;
// prototypes
void moveTortoise( int *const );
void moveHare( int *const );
void printCurrentPositions( const int *const, const int *const );
int main()
{
int tortoise = 1;
int hare = 1;
int timer = 0;
srand( time( 0 ) );
cout << "ON YOUR MARK, GET SET\nBANG !!!!"
<< "\nAND THEY'RE OFF !!!!\n";
// loop through the events
while ( tortoise != RACE_END && hare != RACE_END )
{
moveTortoise( &tortoise );
moveHare( &hare );
printCurrentPositions( &tortoise, &hare );
timer++;
} // end loop
if ( tortoise >= hare )
cout << "\nTORTOISE WINS!!! YAY!!!\n";
else
cout << "\nHare wins. Yuch.\n";
cout << "\nTIME ELAPSED = " << timer << " seconds" << "\n" << endl;
system("pause");
return 0; // indicates successful termination
} // end main
// progress for the tortoise
void moveTortoise( int * const turtlePtr )
{
int x = 1 + rand() % 10; // random number 1-10
if ( x >= 1 && x <= 5 ) // fast plod
*turtlePtr += 3;
else if ( x == 6 || x == 7 ) // slip
*turtlePtr -= 6;
else // slow plod
++( *turtlePtr );
if ( *turtlePtr < 1 )
*turtlePtr = 1;
else if ( *turtlePtr > RACE_END )
*turtlePtr = RACE_END;
} // end function moveTortoise
// progress for the hare
void moveHare( int * const rabbitPtr )
{
int y = 1 + rand() % 10; // random number 1-10
if ( y == 3 || y == 4 ) // big hop
*rabbitPtr += 9;
else if ( y == 5 ) // big slip
*rabbitPtr -= 12;
else if ( y >= 6 && y <= 8 ) // small hop
++( *rabbitPtr );
else if ( y > 8 ) // small slip
*rabbitPtr -= 2;
if ( *rabbitPtr < 1 )
*rabbitPtr = 1;
else if ( *rabbitPtr > RACE_END )
*rabbitPtr = RACE_END;
} // end function moveHare
// display new position
void printCurrentPositions( const int * const snapperPtr,
const int * const bunnyPtr )
{
if ( *bunnyPtr == *snapperPtr )
cout << setw( *bunnyPtr ) << "OUCH!!!";
else if ( *bunnyPtr < *snapperPtr )
cout << setw( *bunnyPtr ) << 'H'
<< setw( *snapperPtr - *bunnyPtr ) << 'T';
else
cout << setw( *snapperPtr ) << 'T'
<< setw( *bunnyPtr - *snapperPtr ) << 'H';
cout << '\n';
} // end function printCurrentPositions
In C++ you can use references instead of pointers. For example, instead of
void foo(int *x) {
*x = *x + 1;
}
int main() {
int a = 0;
foo(&a);
return 0;
}
you can pass x by reference, like so:
void foo(int &x) {
x = x + 1;
}
int main() {
int a = 0;
foo(a);
return 0;
}
Passing a reference is sort of like passing a pointer, except you don't need to dereference the pointer every time you want to access the value it points to.
You can google "C++ pass by reference" for more information, such as this tutorial: http://www.learncpp.com/cpp-tutorial/73-passing-arguments-by-reference/
Alternatively, in your program, you could simply pass int arguments and return the new value:
int moveTortoise(int turtle) {
...
turtle = turtle + 3;
...
return turtle;
}
tortoise = moveTortoise(tortoise)
References& and pointers* are usefull when:
1. you deal with instances of complex classes that passing by reference is resource(CPU time & main memory) consuming operation;
2. when you want to change arguments what are passed(as any function in C++ can return only one value, opposit for ex. to python where multiply values can be returned, you can cope with that restriction by passing using & or *);
3. Other cases...
Built-in(atomic) types can be passed by value (which is you case) without decrease in efficiency.
I am working on a client server application, where client compresses a 2MB data sends to the server, server receives the data uncompresses it and writes it to a file.
For some packets uncompression was failing and I added MD5 sum to both client side and server side code and also debugged using uncompression at the client side after compressing the data. The same parameters that passes for uncompress function in client side is failing with Z_DATA_ERROR in the server side. The data's MD5sum seems same. Am totally clueless what I could do next.
Server Side cod looks like this:
int ret = uncompress((Bytef*)unCompressedBuffer, &dwUncompressedBytes, (const Bytef*) receivedBuffer+525, dwBlockLength);
if (ret == Z_OK)
{
}
else
{
std::cout << " Uncompression failed for Block: " << iBlock << std::endl;
std::cout << " PacketType: 4" << " Block Number:" << iBlock << " Length:" << dwBlockLength << "Error:" << ret << std::endl;
PrintMD5SumResult((PBYTE)receivedBuffer+525, compressedSize-525);
std::cout << " Uncompressed MD5 Checksum:0";
PrintMD5SumResult((PBYTE)unCompressedBuffer, dwUncompressedBytes);
}
}
Client Code Looks like this:
int ret = compress2(l_pCompressData + 4, &destLen,
(const Bytef*) pBlockData, dwBlockSize, 6);
memcpy(m_pWriteBuffer+525, l_pCompressData, destLen);
m_dwWriteBytes = destLen+525;
std::cout << " \n Compressed MD5 Sum:0";
PrintMD5SumResult(m_pWriteBuffer, m_dwWriteBytes);
PrintMD5SumResult(m_pWriteBuffer+525, m_dwWriteBytes-525);
int ret = uncompress(m_pUnCompressData, &uncomLen, (const Bytef*)m_pWriteBuffer+525, destLen);
if(ret != Z_OK)
{
std::cout << " Uncompression has failed." << std::endl;
}
else
{
//std::cout << " UnCompressed MD5 Sum:0";
//PrintMD5SumResult((PBYTE)m_pUnCompressData, md5Output, dwBlockSize);
}
// Write the 2MB to the network
WriteDataOverNetwork(m_NetworkStream, m_pWriteBuffer, m_dwWriteBytes, &dwNumBytes, TRUE);
I narrowed down the problem to the following piece of code in zlib - but have a hard time understanding it. In the inflate() function, (ZSWAP32(hold)) != state->check) this statement is failing. Can someone help me out here? MD5sum used here is from Boton C++ library.
case CHECK:
if (state->wrap) {
NEEDBITS(32);
out -= left;
strm->total_out += out;
state->total += out;
if (out)
strm->adler = state->check =
UPDATE(state->check, put - out, out);
out = left;
if ((
#ifdef GUNZIP
state->flags ? hold :
#endif
ZSWAP32(hold)) != state->check) {
strm->msg = (char *)"incorrect data check";
state->mode = BAD;
break;
}
I also met this issue recently when I used zlib to do in-memory compression/decompression. The code is as follow:
size_t size = 1048576;
void *data;
void *comp_data;
uLong comp_data_len;
void *uncomp_data;
uLong uncomp_data_len;
void *temp;
int ret;
data = calloc(1, size); // data is filled with all zeros
comp_data_len = size * 1.01 + 12;
comp_data = calloc(1, size);
ret = compress(comp_data, &comp_data_len, data, size); //here ret is Z_OK.
uncomp_data_len = size;
uncomp_data = calloc(1, uncomp_data_len);
ret = uncompress(uncomp_data, &uncomp_data_len, comp_data, comp_data_len); //here ret is Z_OK
temp = calloc(1, 496);
for (i = 0; i < 100; i++)
{
//here fill some random data to temp
memcpy((char*)data + i * 100, temp, 496);
ret = compress(comp_data, &comp_data_len, data, size); //here ret is Z_OK.
ret = uncompress(uncomp_data, &uncomp_data_len, comp_data, comp_data_len); //here ret sometimes is Z_OK, sometimes is Z_DATA_ERROR!!!
}
I also traced the code and found that it failed at the statement "inflate() function, (ZSWAP32(hold)) != state->check)" too. So I cannot believe that the function uncompress is related to the data pattern. Am I wrong?
I also noticed that compress function calls deflate to do compression, deflate processes data every 64k, so need I split it to 64k blocks, compress each block one by one, then uncompress can work well?
i don't know whether it‘s the right answer ,maybe it help !my English is so poor,hope you can understand. perhaps the parameters convert to another has bugs . when they convert the info maybe lose ! i meet the same problem , after use the source code type the problem has been solved (Bytef\uLongf\ uLong,etc). the wed is Chinese you can use Google to translate.
http://www.360doc.com/content/13/0927/18/11217914_317498849.shtml
This is my test.the arry[] can be larger,same time the sour[]/dest[]/destLen/Len will be changed.using the source code type the problem has been solved. Hope will be helpful.
my code as follow:
#include <stdio.h>
#include "zlib.h"
int main(){
//the buffer can be larger
Bytef arry[] = "中文测试 yesaaaaa bbbbb ccccc ddddd 中文测试 yesaaaaa bbbbb ccccc ddddd 中文测试yesaaaaa bbbbb ccccc ddddd 中文测试 yes 我是一名军人!";
//buffer length
int size = sizeof(arry);
//store the uncompressed data
Bytef sour[2500];
//store the compressed data
Bytef dest[2500];
//压缩后的数据可能比源数据要大
unsigned long destLen = 2500;
//解压数据时因为不知道源数据大小,设置时长度尽可能大一些。以免出错
unsigned long Len = 2500;
int ret = -1;
ret = compress(dest,&destLen,arry,size);
//dest[destLen] = '\0';
printf("ret = %d\ndest = %s\n", ret, dest);
ret = uncompress(sour,&Len,dest,destLen);
//sour[size-1] = '\0';
printf("ret = %d\nsour = %s\n", ret, sour);
return 0;
}
Hi I wrote a simple c prog to just accept a password while diplaying * to hide the input. But the * for the last character entered is not appearing at the right place.
the code is below
int main(){
int choice = 0;
char pass[8];
FILE *input;
FILE *output;
struct termios initial_settings, new_settings;
if(!isatty(fileno(stdout))){
fprintf(stderr,"Not a terminal \n");
}
input = fopen("/dev/tty","r");
output = fopen("/dev/tty","w");
if(!input || !output){
fprintf(stderr,"error opening");
exit(1);
}
tcgetattr(fileno(input),&initial_settings);
new_settings = initial_settings;
new_settings.c_lflag &= ~ICANON;
new_settings.c_lflag &= ~ECHO;
new_settings.c_cc[VMIN] = 1;
new_settings.c_cc[VTIME] = 0;
new_settings.c_lflag &= ~ISIG;
if(tcsetattr(fileno(input), TCSANOW, &new_settings) != 0) {
fprintf(stderr,"could not set attributes\n");
}
int count = 0;
char ch;
printf("Please enter the password: ");
while (count<8){
ch = fgetc(input);
if(ch == '\n' || ch == '\r'){
break;
}else{
fputc('*',stdout);
pass[count] = ch;
count++;
}
tcdrain(fileno(stdout));
}
fprintf(output,"you have entered :%s \n",pass);
tcsetattr(fileno(input),TCSANOW,&initial_settings);
exit(0);
}
The output is as follows:
Please enter the password:* * * * * * *
you have entered :12345678
* pasman#pasman-laptop:~$
Its an 8 character password & Notice that 7 *s appear as expected but the last * is appearing at the end of main.
You're mixing stdio and another stream, output, talking directly to the tty. They have different buffers, and get flushed at different times. You really should just use one of them.
It's because you break before you write the last *: so
add
fputc('*',stdout);
before
tcdrain(fileno(stdout));