Incluir msvcr100.dll al compilar

VipeR_CS

Veamos, me ocurre lo siguiente:

Tengo un programa en C++ con Visual Studio 2010 y necesito que el programa funcione tanto en Windows 7 como en Windows XP. Para ello en las propiedades del proyecto, en "Runtime Library" que se encuentra dentro del apartado "C/C++ -> Code Generation", elijo Multi-Threaded (/MT). Esto hace posible que el programa se ejecute perfectamente en ambos SOs. En Windows 7 todo funciona correctamente y hace lo que debe; sin embargo, en Windows XP hay una parte que no lo hace (un cálculo, muestra -8083 cuando debería mostrar -803 por ejemplo).

Por otro lado, si compilo con la Runtime Library en "Multi-Threaded DLL (/MD)" en Windows 7 sigue funcionando correctamente, pero en Windows XP no se ejecuta porque falta la librería msvcr100.dll. Si copio esa librería en la carpeta del ejecutable, se ejecuta correctamente y el cálculo que antes fallaba, ahora no falla.

Entonces, la solución pasaría por incluir de alguna forma esa librería en la compilación, pero no hay huevos a conseguirlo. He estado trasteando un poco en el Linker en las opciones del proyecto, añadiéndola a Additional Dependencies, pero me da error al compilar. Concretamente este error:

1>C:\Windows\System32\msvcr100.dll : fatal error LNK1107: invalid or corrupt file: cannot read at 0x360
1>
1>Build FAILED.

¿Alguna idea para solucionar este caos? xD Gracias.

r2d2rigo

msvcr100.dll pertenece al common runtime de VS, y deberia estar instalado en el equipo de destino para que funcione correctamente: http://msdn.microsoft.com/en-us/library/abx4dbyh.aspx

Si te falla cuando compilas con /MT es simplemente porque estas asumiendo que tu aplicacion es threadsafe cuando en realidad no lo es, asi que arregla los fallos que tengas y redistribuyela asi, que ahorraras problemas al usuario final.

2 respuestas
VipeR_CS

#2 Pues la verdad es que en ese tema ando más perdido que un mono en un garaje. Voy a leerme http://en.wikipedia.org/wiki/Thread_safety a ver si me entero de algo, pero me resulta difícil identificar el error cuando realmente no hay error, porque en Windows 7 funciona bien y en Windows XP no xD.

El fallo está aislado en este fragmento de código:

void sqlcode() {
	char abc[] = {'{','A','B','C','D','E','F','G','H','I','}','J','K','L','M','N','O','P','Q','R'};
	char str[5] = {0};
	char* cod_num;
	char letra;

fflush(stdin);

do {	
	scanf("%s", &str);	
	letra = str[2];

	if (strlen(str) <= 3) {
		cod_num = (char*)malloc(sizeof(str)-1);
		strncpy(cod_num, str, strlen(str)-1);
	}

} while ( letra < 65 || ( letra > 82 &&  letra != 123 && letra != 125) );

int posicion = getPosicion(abc,letra);
int signo = posicion/9; //0=positivo 1=negativo
int valor = posicion%9;
int total = atoi(cod_num)*10+valor-signo;
total = ((signo)?-1:1)*total;
printf("\n     El c\242digo resultante es: %d\n\n",total);

getch();

system("cls");
imprimir_cabecera();
}


int getPosicion(char abc[], char letra) {
	int i=0; 

for (i=0;i<20;i++)
	if (abc[i] == letra)
		return i;

return -1;
}

Si alguien ve algo que no sea threadsafe así de primeras genial, sino ya me pegaré con ello a ver qué pasa.

Edit: creo haberlo aislado a esto, ya que el resto de valores salen correctamente en Windows XP. Sin embargo el total no.

int total = atoi(cod_num)*10+valor-signo;
VipeR_CS

FUCK YES lo conseguí, su puta madre xD el problema no era estaba finalmente en la linea que pensaba en #2 (aunque ya de paso me cambié atoi por strtol, que atoi tampoco era thread-safe por lo visto).

Lo que he hecho ha sido añadir después de:

if (strlen(str) <= 3) {
                        cod_num = (char*)malloc(sizeof(str)-1);
                        strncpy(cod_num, str, strlen(str)-1);
                }

la siguiente línea:

cod_num[strlen(str)-1] = '\0';

Parece que de momento ya hace el cálculo bien en ambos SOs. No sé ni porqué pero bueno, el caso es que funciona.

Gusete

#1 Echale un ojo a este enlace http://msdn.microsoft.com/en-us/library/abx4dbyh.aspx . En resumen:
MT (Multithreaded): La libreria de c++ (y/o c) de windows es estatica, cuando compilas tu programa va "empotrada" en el ejecutable.
MTD (Multithreaded DLL): La libreria de c++ (y/o c) de windows es dinamica, cuando compilas tu programa no se añade la libreria al ejecutable. La libreria, en forma de dll, tendra que estar disponible en tiempo de ejecucion.

Microsoft no recomienda compilar en MT, porque si en un futuro cambian el runtime (por ejemplo, arreglan un bug o un exploit) tendras que volver a compilar tu programa, con todo lo que supone. En cambio, con MTD, pueden cambiar el runtime (hasta cierto punto) y tu programa se vera automaticamente beneficiado sin tu hacer nada o simplemente actualizando las dlls. El "problema" con MTD es que las variables estaticas de la libreria son compartidas por todos los programas que linkan a esa dll. Asi que si quieres usar funciones que usen variables estaticas internas, es preferible que escojas la alternativa segura (normalmente marcada con un "_s" al final del nombre de la funcion).

Normalmente lo que se hace, en mi experiencia, es compilar en modo MTD e instalar, ademas del programa, el runtime. Microsoft te permite que distribuyas en tu programa el instalador del runtime sin coste (Te lo puedes bajar de aqui http://www.microsoft.com/download/en/details.aspx?id=5555 ). Si es para algo pequeño, es bastante comun incluir directamente las dll del runtime(las puedes encontrar en alguna carpeta de visual studio, seguramente llamada redist aqunque no me acuerdo) en tu paquete(zip/instalador/...) pero no se si esto infringiria la licencia de microsoft.

Otra cosa, me choca que digas que es un programa en C++ y el codigo que has mostrado sea C. Si puedes usar C++, ¿no te seria mas facil usar las stl? :)

1 respuesta
VipeR_CS

#5 Bueno es que mi C++ es un poco peculiar. En realidad sí que es C en su mayoría, pero mezclo cosas por ahí de C++ según me parece xD. No es nada profesional, ni tiene instalador. Es un programa de consola, así que lo de incluir el runtime no es una opción. Además los PCs a los que está destinado no tienen permisos de administrador, no podría instalarlo. No me queda más huevos que compilarlo en MT me temo xD.

Aún así gracias por la información, seguro que me será útil para futuros programas.

1 respuesta
Gusete

#6 Como te he dicho, normalmente para cosas pequeñas simplemente se coge las dlls del runtime y se distribuyen con el programa. Las dlls las puedes encontrar en la carpeta del visual studio. De todas formas, si no quieres copiar un archivo mas, tienes en cuenta lo que conlleva compilar en MT (por ejemplo, lo de las variables estaticas) y tu proyecto no es profesional, me parece lo mas comodo para tu caso. :)

"Bueno es que mi C++ es un poco peculiar. En realidad sí que es C en su mayoría, pero mezclo cosas por ahí de C++ según me parece xD"
:P Ten cuidado como mezclas malloc y new! XD. Si puedes usar C++, yo te recomendaria que dejaras de usar la libreria de C y usases la libreria de C++, te hace la vida muchisimo mas facil.

1 respuesta
VipeR_CS

#7 Lo de incluir el runtime también es una buena opción sí. Se puede bajar de la página de microsoft pero claro, es un ejecutable que te lo instala y sabe Dios los archivos que instala para copiarlos, y como digo no puedo instalar nada en los ordenadores donde iría finalmente el programa. De todas formas con copiar simplemente el msvcr100.dll funcionaba, el resto podría pasar sin ellos imagino.

Por cierto ya puestos en materia, eso de copiar el msvcr100.dll funciona siempre que sea en la misma carpeta que el ejecutable (o system32 en su defecto imagino), pero hay alguna forma de poder meterlo en una carpeta "/DLLs" y que el ejecutable la pille? Esto ya es curiosidad más que nada, por hacer las cosas bien xD

1 respuesta
Gusete

#8 http://msdn.microsoft.com/en-us/library/7d83bc18%28v=VS.100%29.aspx

En principio, deberias poder hacerlo modificando la variable de entorno "PATH". No tengo ni idea de si hay una forma mejor, tal vez modificando el manifest, pero ni idea, nunca he tenido que hacerlo. :)

1 respuesta
VipeR_CS

#9 He estado mirando y parece que con las funciones putenv y getenv debería servir. El problema es que en vez de añadir la ruta que le meto al PATH, se carga todo y pone únicamente esa. No sé para qué me complico tanto la vida, al final compilo con MT o meto la dll con el ejecutable y que le den por culo xD

2 meses después
CaLaTa

A ver, que me parece que tengo el mismo problema.

El caso es que ya tengo echa mi aplicación y la compilo para hacerla instalación. Cuando la instalo en el mismo ordenador en el que la he desarrollado con VS2010, quito los directorios del PATH de las variables de entorno para comprobar que los .dll que necesitaba van bien al incluirlos en la instalación.

En ese ordenador me funciona bien, pero al instalarlo en otro ordenador (con la redistribución) me tira un error y si hago un debug muy simple me pone que es por culpa del msvcr100.dll. Puede ser mi problema por el thread-safe tambien? (siento no poner código, que ahora mismo no estoy donde tengo el código fuente).

1 respuesta
elkaoD

#11 lo que tienes que poner no es código, sino el error. ¿Qué mierda es eso de "me tira un error"? ¡DETALLES!

CaLaTa

Nada, ya está solucionado. Era una gilipoyez como una catedral. Intentaba crear un archivo y no tenía permisos porque no existía la carpeta.

Usuarios habituales

  • CaLaTa
  • elkaoD
  • VipeR_CS
  • Gusete
  • r2d2rigo